<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"><title>一、GC 性能优化 – G1垃圾收集器入门 | 云少IT</title><meta name="keywords" content="JVM"><meta name="author" content="云少"><meta name="copyright" content="云少"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="mobile-web-app-capable" content="yes"><meta name="apple-touch-fullscreen" content="yes"><meta name="apple-mobile-web-app-title" content="一、GC 性能优化 – G1垃圾收集器入门"><meta name="application-name" content="一、GC 性能优化 – G1垃圾收集器入门"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="#ffffff"><meta property="og:type" content="article"><meta property="og:title" content="一、GC 性能优化 – G1垃圾收集器入门"><meta property="og:url" content="https://it985.github.io/posts/5333e17a.html"><meta property="og:site_name" content="云少IT"><meta property="og:description" content="一、GC 性能优化 – G1垃圾收集器入门G1垃圾收集器入门 master ，这是我的小站,欢迎访问哦~~  说明concurrent: 并发, 多个线程协同做同一件事情(有状态) parallel: 并行, 多个线程各做各的事情(互相间无共享状态) 在GC领域: concurrent算法指GC线程"><meta property="og:locale" content="zh-CN"><meta property="og:image" content="https://cn.bing.com/th?id=OHR.SmileySloth_EN-US8588687884_UHD.jpg"><meta property="article:author" content="云少"><meta property="article:tag" content="云少IT,IT,技术,分享,程序员,博客,教程,工具,框架,bug,java,spring,数据库,"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://cn.bing.com/th?id=OHR.SmileySloth_EN-US8588687884_UHD.jpg"><meta name="description" content="一、GC 性能优化 – G1垃圾收集器入门G1垃圾收集器入门 master ，这是我的小站,欢迎访问哦~~  说明concurrent: 并发, 多个线程协同做同一件事情(有状态) parallel: 并行, 多个线程各做各的事情(互相间无共享状态) 在GC领域: concurrent算法指GC线程"><link rel="shortcut icon" href="/img/logo.webp"><link rel="canonical" href="https://it985.github.io/posts/5333e17a"><link rel="preconnect" href="//npm.elemecdn.com"><link rel="preconnect" href="//npm.onmicrosoft.cn"><link rel="preconnect" href="//www.google-analytics.com" crossorigin=""><link rel="preconnect" href="//busuanzi.ibruce.info"><meta name="google-site-verification" content="NuBZ4r-QCqSgo4XUScdEsQW0bolIHEiVGq4A16ndPQA"><meta name="baidu-site-verification" content="code-xxx"><meta name="msvalidate.01" content="xxx"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.cbd.int/@fortawesome/fontawesome-free@6.4.0/css/all.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://cdn.cbd.int/node-snackbar@0.1.16/dist/snackbar.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://cdn.cbd.int/@fancyapps/ui@5.0.20/dist/fancybox/fancybox.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://npm.elemecdn.com/anzhiyu-theme-static@1.0.0/swiper/swiper.min.css" media="print" onload='this.media="all"'><script async src="https://www.googletagmanager.com/gtag/js?id=G-3VMKW5TZBM"></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-3VMKW5TZBM")</script><script>const GLOBAL_CONFIG={linkPageTop:{enable:!0,title:"与数百名博主无限进步",addFriendPlaceholder:"昵称（请勿包含博客等字样）：\n网站地址（要求博客地址，请勿提交个人主页）：\n头像图片url（请提供尽可能清晰的图片，我会上传到我自己的图床）：\n描述：\n站点截图（可选）：\n"},peoplecanvas:void 0,postHeadAiDescription:{enable:!0,gptName:"云AI",mode:"tianli",switchBtn:!1,btnLink:"https://afdian.net/item/886a79d4db6711eda42a52540025c377",randomNum:3,basicWordCount:1e3,key:"48580d1e3f53ae174a1e",Referer:"https://blog.tryrun.top"},diytitle:{enable:!0,leaveTitle:"w(ﾟДﾟ)w 不要走！再看看嘛！",backTitle:"♪(^∇^*)欢迎肥来！"},LA51:{enable:!0,ck:"JiFOrFoQklEn9YLS",LingQueMonitorID:"JiqlTmdeI4e1fPbd"},greetingBox:{enable:!0,default:"晚上好👋",list:[{greeting:"晚安😴",startTime:0,endTime:5},{greeting:"早上好鸭👋, 祝你一天好心情！",startTime:6,endTime:9},{greeting:"上午好👋, 状态很好，鼓励一下～",startTime:10,endTime:10},{greeting:"11点多啦, 在坚持一下就吃饭啦～",startTime:11,endTime:11},{greeting:"午安👋, 宝贝",startTime:12,endTime:14},{greeting:"🌈充实的一天辛苦啦！",startTime:14,endTime:18},{greeting:"19点喽, 奖励一顿丰盛的大餐吧🍔。",startTime:19,endTime:19},{greeting:"晚上好👋, 在属于自己的时间好好放松😌~",startTime:20,endTime:24}]},twikooEnvId:"https://twikoo.tryrun.top/",commentBarrageConfig:void 0,root:"/",preloader:{source:2},friends_vue_info:{apiurl:"https://friends.tryrun.top/"},navMusic:!1,mainTone:void 0,authorStatus:{skills:["🤖️ 数码科技爱好者","🔍 分享与热心帮助","🏠 智能家居小能手","🔨 设计开发一条龙","🤝 专修交互与设计","🏃 脚踏实地行动派","🧱 团队小组发动机","💢 壮汉人狠话不多"]},algolia:{appId:"T5VW6VDYLS",apiKey:"227bcb041816af13cb1698db15a8ac89",indexName:"hexo-blog",hits:{per_page:6},languages:{input_placeholder:"输入关键词后按下回车查找",hits_empty:"找不到您查询的内容：${query}",hits_stats:"找到 ${hits} 条结果，用时 ${time} 毫秒"}},localSearch:void 0,translate:{defaultEncoding:2,translateDelay:0,msgToTraditionalChinese:"繁",msgToSimplifiedChinese:"简",rightMenuMsgToTraditionalChinese:"转为繁体",rightMenuMsgToSimplifiedChinese:"转为简体"},noticeOutdate:{limitDay:365,position:"top",messagePrev:"It has been",messageNext:"days since the last update, the content of the article may be outdated."},highlight:{plugin:"highlighjs",highlightCopy:!0,highlightLang:!0,highlightHeightLimit:330},copy:{success:"复制成功",error:"复制错误",noSupport:"浏览器不支持"},relativeDate:{homepage:!0,simplehomepage:!1,post:!0},runtime:"天",date_suffix:{just:"刚刚",min:"分钟前",hour:"小时前",day:"天前",month:"个月前"},copyright:void 0,lightbox:"fancybox",Snackbar:{chs_to_cht:"你已切换为繁体",cht_to_chs:"你已切换为简体",day_to_night:"你已切换为深色模式",night_to_day:"你已切换为浅色模式",bgLight:"#425AEF",bgDark:"#1f1f1f",position:"top-center"},source:{justifiedGallery:{js:"https://cdn.cbd.int/flickr-justified-gallery@2.1.2/dist/fjGallery.min.js",css:"https://cdn.cbd.int/flickr-justified-gallery@2.1.2/dist/fjGallery.css"}},isPhotoFigcaption:!1,islazyload:!0,isAnchor:!1,shortcutKey:void 0,autoDarkmode:!0}</script><script id="config-diff">var GLOBAL_CONFIG_SITE={configTitle:"云少IT",title:"一、GC 性能优化 – G1垃圾收集器入门",postAI:"true - 优化",pageFillDescription:"一、GC 性能优化 – G1垃圾收集器入门, G1垃圾收集器入门, 说明, 概述, Java 技术 和 JVM, Java 概述, 探索 JVM 体系架构, 性能基础, G1 垃圾收集器(Garbage Collector), G1 垃圾收集器, CMS的GC概述, 分代GC(Generational GC)与 CMS, G1垃圾收集器概述, 一步步介绍G1, Old Generation Collection with G1, 命令行参数与最佳实践, 命令行参数与最佳实践, 记录G1的GC日志, 记录G1的GC日志, 总结, 相关资源一性能优化垃圾收集器入门垃圾收集器入门这是我的小站欢迎访问哦说明并发多个线程协同做同一件事情有状态并行多个线程各做各的事情互相间无共享状态在领域算法指线程和业务线程能并发执行指线程之间的并行参考概述目的本文介绍如何使用及在中怎么使用垃圾收集器您将了解收集器的内部原理切换为收集器的命令行参数以及让其记录日志的选项需要的时间大约个小时简介本文涵盖了虚拟机中的基础知识第一部分简单概述的同时介绍了垃圾收集和性能接下来讲述了中收集器是如何工作的接着再一步一步地指导在中使用进行垃圾回收的工作方式之后的一个小节介绍垃圾收集器可用的命令行参数最后您将了解如何配置使收集器记录日志硬件与软件环境需求下面是硬件与软件环境需求清单一台机运行以上操作系统或者都可以注意因为作者在上进行开发和测试尚未在所有平台上完成测试但在和上应该也是正常的最好配置了多核或更高版本最新的文件准备条件在开始学习本教程之前你需要下载并安装最新的或以后的版本下载页面下载并安装示例与样例文件下载页面和相同然后解压到合适的位置如技术和概述是公司在年发布的一门编程语言同时也是一个运行程序的底层平台提供工具游戏和企业应用程序支持运行在全世界超过亿的以及数十亿的智能设备上包括和是由许多关键部件组成的一个整体统称为平台一般来说下载了以后你就得到了一个运行时由虚拟机平台核心类以及平台支持库组成必须有这三大组件的支持才能在你的电脑上运行程序例如可以在操作系统上作为桌面应用程序运行还可以通过从上安装或者是作为嵌入式程序在浏览器中运行通过编程语言是一门面向对象编程语言包涵以下特性应用程序被编译为字节码存放到文件中由加载因为程序在中运行所以可以跨平台运行在各种操作系统设备上是一门面向对象的语言继承了和的很多特性并在此基础上进行扩充和优化对内存进行自动分配和自动释放所以程序不再执行这一繁琐的任务其实自动内存回收更多的好处是减少了编程需要重复处理的这种细节另一个例子是对的封装包含大量的标准对象可以执行诸如输入输出网络操作以及日期处理等任务是用来开发程序的一系列工具集通过你可以编译用语言书写的程序并在中运行另外还提供了打包和分发程序的工具和使用同样的是预先打包好以供程序员用来开发程序的类库集合通过使得很多常规任务可以很轻松的就完成如字符串操作时间日期处理网络编程以及实现各种数据结构如是一台抽象的计算机本质是一个程序但在运行于上的程序看来他就像一台真实机器一样这样程序就能使用相同的接口和库每种特定操作系统上的实现都将程序指令转换为本地机器的指令和命令由此实现了程序的平台独立性虚拟机的第一个原型实现由完成在一台手持设备上用软件模拟了虚拟机指令集类似于今天的当前在移动设备桌面系统和服务器上都提供了虚拟机实现但虚拟机不限制使用任何特定的技术硬件或操作系统也不一定都是基于软件的你可以直接在硬件上实现指令还可以芯片上实现或者采用的方式来实现虚拟机完全不关心语言的细节只识别文件这种特定的二进制格式一个文件包含虚拟机指令或称之为字节码及符号变量表还有一些辅助信息基于安全性考虑虚拟机对文件中的代码执行强语法检查和组成结构规范限制既然虚拟机有这种特征那么任何一门编程语言只要能编译为合法的文件都可以加载到虚拟机里面执行由于具有通用性跨平台特性其他语言的实现者可以把虚拟机作为该语言的加载执行工具探索体系架构架构有一个稳定强悍的架构支持强大的功能与特性具备实现高性能和大规模可伸缩性的能力例如编译器能动态进行优化生成换句话说他们运行程序时会针对底层系统架构动态生成高性能的本地机器指令此外通过成熟的演进和运行时环境的持续工程加上多线程垃圾收集器即使实在大型计算机系统上也能获得很高的伸缩性的主要组件包括类加载器运行时数据区以及执行引擎关键部分与性能有关的部分是最重要的组件下图中用高亮的颜色来显示对进行性能调优时有三大组件需要重点关注堆是存放对象的内存空间这个区域由启动时选择的垃圾收集器进行管理大多数调优参数都是调整堆内存的大小以及根据实际情况选择最合适的垃圾收集器编译器也对性能有很大的影响但新版本的调优中很少需要关注性能基础大多数情况下对程序进行调优主要关注两个目标之一响应速度和或吞吐量下面的教程中我们将讲述这些概念响应能力响应能力就是程序或系统对一个请求的响应有多迅速比如程序响应速度有多灵敏网站页面响应有多快数据库查询有多快对响应速度要求很高的系统较大的停顿时间是不可接受的重点是在非常短的时间周期内快速响应吞吐量吞吐量关注在一个特定时间段内应用系统的最大工作量衡量吞吐量的指标示例包括给定时间内完成的事务数每小时批处理系统能完成的作业数量每小时能完成多少次数据库查询在吞吐量方面优化的系统停顿时间长也是可以接受的由于高吞吐量应用运行时间长所以此时更关心的是如何尽可能快地完成整个任务而不考虑快速响应垃圾收集器垃圾收集器是一款面向服务器的垃圾收集器主要针对配备多颗处理器及大容量内存的机器以极高概率满足停顿时间要求的同时还具备高吞吐量性能特征在及以上版本中得到完全支持专为以下应用程序设计可以像收集器一样操作与应用的线程一起并发执行紧凑的空闲内存区间且没有很长的停顿时间需要可预测的暂停耗时不想牺牲太多吞吐量性能启动后不需要请求更大的堆的长期目标是取代并发标记清除因为特性的不同使成为比更好的解决方案一个区别是是一款压缩型的收集器通过有效的压缩完全避免了对细微空闲内存空间的分配不用依赖于这不仅大大简化了收集器而且还消除了潜在的内存碎片问题除压缩以外的垃圾收集停顿也比容易估计也允许用户自定义所希望的停顿参数操作概述上一代的垃圾收集器串行并行以及都把堆内存划分为固定大小的三个部分年轻代年老代以及持久代内存中的每个对象都存放在这三个区域中的一个而收集器采用一种不同的方式来管理堆内存堆内存被划分为多个大小相等的区每个区都是逻辑上连续的一段内存其中一部分区域被当成老一代收集器相同的角色但每个角色的区域个数都不是固定的这在内存使用上提供了更多的灵活性执行垃圾回收的处理方式与相似在全局标记阶段并发执行以确定堆内存中哪些对象是存活的标记阶段完成后就可以知道哪些区的空间最大它会首先回收这些区通常会得到大量的自由空间这也是为什么这种垃圾收集方法叫做垃圾优先的原因顾名思义将精力集中放在可能布满可收回对象的区域可回收对象也就是所谓的垃圾使用暂停预测模型来达到用户定义的目标暂停时间并根据目标暂停时间来选择此次进行垃圾回收的区域数量被标记为适合回收的区将使用转移的方式进行垃圾回收将一个或多个区域中的对象拷贝到其他的单个区域中并在此过程中压缩和释放内存在多核上转移是并行执行的这样能减少停顿时间并增加吞吐量因此每次垃圾收集时都会持续不断地减少碎片并且在用户给定的暂停时间内执行这比以前的方法强大了很多垃圾收集器并发标记清理不进行压缩垃圾收集只对整个堆执行压缩从而导致相当长的暂停时间需要强调的是并不是一款实时垃圾收集器能以极高的概率在设定的目标暂停时间内完成但不保证绝对在这个时间内完成基于以前收集的各种监控数据会根据用户指定的目标时间来预估能回收多少个区因此收集器有一个相当精确的区耗时计算模型并根据该模型来确定在给定时间内去回收哪些区注意分为两个阶段并发阶段与应用线程一起运行如细化标记清理和并行阶段多线程执行如停止所有线程而完整垃圾收集仍然是单线程的但如果进行适当的调优则应用程序应该能够避免的内存占用如果从或者收集器迁移到您可能会看到进程占用更多的内存这在很大程度上与数据结构有关如和简称跟踪指向某个区内的对象引用堆内存中的每个区都有一个使区能并行独立地进行垃圾集合的总体影响小于简称收集集合在一次中将执行垃圾回收的区时在中的所有存活数据都会被转移复制移动集合中的区可以是和或所占用的内存小于推荐使用的场景的首要目标是为需要大量内存的系统提供一个保证低延迟的解决方案也就是说堆内存在及以上稳定和可预测的暂停时间小于秒如果应用程序具有如下的一个或多个特征那么将垃圾收集器从或切换到将会大大提升性能次数太频繁或者消耗时间太长对象分配的频率或代数提升显著变化受够了太长的垃圾回收或内存整理时间超过秒注意如果正在使用或而应用程序的垃圾收集停顿时间并不长那么继续使用现在的垃圾收集器是个好主意使用最新的时并不要求切换到收集器的概述分代与并发标记清理收集器也称为多并发低暂停的收集器回收老年代内存它将垃圾回收中的绝大部分工作与应用程序的线程一起并发执行以期能最小化暂停时间通常多并发低暂停收集器收集器不复制或也不压缩存活的对象垃圾回收不移动存活的对象如果产生内存碎片问题就会分配占用更大的堆内存空间注意年轻代使用的收集器也和并行收集器采用一样的算法垃圾收集阶段划分收集器在老年代堆内存的回收中执行分为以下阶段阶段说明初始标记所有应用线程暂停在老年代中的对象如果从年轻代中能访问到则被标记为可达的对象在旧一代标志可以包括这些对象可能可以从年轻一代暂停时间一般持续时间较短相对小的收集暂停时间并发标记在应用程序线程运行的同时遍历老年代的可达对象图扫描从被标记的对象开始直到遍历完从可达的所有对象调整器在并发阶段的阶段执行在这些阶段中新分配的所有对象包括被提升的对象都立刻标记为存活状态再次标记所有应用线程暂停查找在并发标记阶段漏过的对象这些对象是在并发收集器完成对象跟踪之后由应用线程更新的并发清理回收在标记阶段确定为不可及的对象死对象的回收将此对象占用的空间增加到一个空闲列表供以后的分配使用死对象的合并可能在此时发生请注意存活的对象并没有被移动重置清理数据结构为下一个并发收集做准备的步骤接下来让我们一步步地讲述收集器的操作的堆内存结构堆内存被分为个空间年轻代分为个新生代空间和个存活区老年代是一大块连续的空间垃圾回收就地解决除了否则不会进行压缩年轻代的工作方式年轻代用高亮的绿色表示老年代用蓝色表示如果程序运行了一段时间那么看起来就像下图这个样子对象散落在老年代中的各处地方在使用时老年代的对象回收就地进行他们不会被移动到其他地方除了否则内存空间不会进行压缩年轻代垃圾回收区和区中的存活对象被拷贝到另一个空的区存活时间更长达到阀值的对象会被提升到老年代年轻代之后年轻代进行一次垃圾回收之后区被清理干净两个区中的一个也被清理干净了如下图所示图中新提升的对象用深蓝色来标识绿色的部分是年轻代中存活的对象但还没被提升到老年代中的老年代回收两次事件发生在初始标记以及重新标记阶段当老年代达到一定的占有率时垃圾回收器就开始工作初始标记阶段的停顿时间很短在此阶段存活的可及的对象被记下来并发标记在程序继续运行的同时找出存活的对象最后在第阶段查找在第阶段中错过的对象老年代回收并发清理在前面阶段未被标记的对象将会就地释放此处没有压缩备注未标记的对象已死对象老年代回收清理之后在第步之后可以看到很多内存被释放了还应该注意到这里并没有执行内存压缩整理最后收集器进入第阶段重置然后等候下一次的阀值到来垃圾收集器概述一步步介绍收集器采用一种不同的方式来分配堆下面通过图解的方式一步步地讲述系统的堆内存结构堆内存被划分为固定大小的多个区域每个区的大小在启动时就确定了通常生成个左右的区根据堆内存的总大小区的范围允许为到堆空间分配实际上这些区域被映射为逻辑上的和老年代空间图中的颜色标识了每一个区域属于哪个角色存活的对象从一块区域转移复制或移动到另一块区域设计成区的目的是为了并行地进行垃圾回收的同时停止或不停止其他应用程序线程如图所示区可以分配为或老年代区此外还有第四种类型的对象被称为巨无霸区域这种巨无霸区是设计了用来保存比标准块大及以上的对象它们存储在一组连续的区中最后一个类型是堆内存中的未使用区备注截止英文原文发表时巨无霸对象的回收还没有得到优化因此您应该尽量避免创建太大大于的对象中的年轻代堆被分为大约个区最小为最大为蓝色的区保存老年代对象绿色区域保存年轻代对象注意中各代的区不像老一代垃圾收集器一样要求各部分是连续的中的一次年轻代存活的对象被转移到一个或多个存活区如果存活时间达到阀值这部分对象就会被提升到老年代此时会有一次暂停会计算出大小和大小给下一次年轻代使用清单统计信息保存了用来辅助计算诸如暂停时间目标之类的东西也会纳入考虑这种方法使得调整各代区域的尺寸很容易让其更大或更小一些以满足需要的一次年轻代完成后存活对象被转移到存活区或老年代刚刚被提升上来的对象用深绿色显示区用绿色表示总结起来的年轻代收集归纳如下堆一整块内存空间被分为多个区年轻代内存由一组不连续的区组成这使得在需要时很容易进行容量调整年轻代的垃圾收集或者叫会有事件在操作时所有的应用程序线程都会被暂停年轻代通过多线程并行进行存活的对象被拷贝到新的区或者老年代和收集器相似收集器也被设计为用来对老年代的对象进行低延迟的垃圾收集下表描述了收集器在老年代进行垃圾回收的各个阶段收集阶段并发标记周期阶段收集器在老年代堆内存中执行下面的这些阶段注意有些阶段也是年轻代垃圾收集的一部分阶段说明初始标记所有应用线程暂停此时会有一次暂停事件在中这附加在一次正常的年轻代标记可能有引用指向老年代对象的区根扫描根区域扫描区中引用到老年代的引用这个阶段应用程序的线程会继续运行在年轻代可能发生之前此阶段必须完成并发标记在整个堆中查找活着的对象此阶段应用程序的线程正在运行此阶段可以被年轻代打断再次标记所有应用线程暂停完成堆内存中存活对象的标记使用一个叫做起始快照的算法该算法比所使用的算法要快速的多清理所有应用线程暂停并发执行在存活对象和完全空闲的区域上执行统计擦写重置空区并将他们返还给空闲列表并发拷贝所有应用线程暂停产生事件来转移或拷贝存活的对象到新的未使用的区只在年轻代发生时日志会记录为如果在年轻代和老年代一起执行则会被日志记录为老年代收集步骤顺着定义的阶段让我们看看收集器如何处理老年代初始标记阶段存活对象的初始标记被固定在年轻代垃圾收集里面在日志中被记为并发标记阶段如果找到空的区域如用红叉标示的区域则会在阶段立即移除当然清单信息决定了活跃度的计算再次标记阶段空的区域被移除并回收现在计算所有区域的活跃度拷贝清理阶段选择活跃度最低的区域这些区域可以最快的完成回收然后这些区域和年轻代在同时被垃圾收集在日志被标识为所以年轻代和老年代都在同一时间被垃圾收集拷贝清理之后所选择的区域被收集和压缩到下图所示的深蓝色区域和深绿色区域老年代总结总结下来对老年代的有如下几个关键点并发标记清理阶段活跃度信息在程序运行的时候被并行计算出来活跃度信息标识出哪些区域在转移暂停期间最适合回收不像一样有清理阶段再次标记阶段使用的开始快照算法比起所用的算法要快得多完全空的区域直接被回收拷贝清理阶段年轻代与老年代同时进行回收老年代的选择基于其活跃度命令行参数与最佳实践命令行参数与最佳实践在本节中让我们看看的各种命令行选项命令行基本参数要启用收集器请使用下面是启动示例程序的命令行示例位于下载后解压的文件夹中关键命令行开关让使用垃圾收集器设置最大停顿时间指标这是一个软性指标会尽力去达成这个目标所以有时候这个目标并不能达成默认值为毫秒启动并发时的堆内存占用百分比用它来触发并发周期基于整个堆的使用率而不只是某一代内存的使用比例值为则表示一直执行循环默认值为例如全部的或者使用了最佳实践在使用作为垃圾收集器时你应该遵循下面这些最佳实践的指导不要设置年轻代的大小假若通过显式地指定了年轻代的大小则会干扰到收集器的默认行为在垃圾收集时将不再关心暂停时间指标所以从本质上说设置年轻代的大小将禁用暂停时间目标在必要时也不能够增加或者缩小年轻代的空间因为大小是固定的所以对更改大小无能为力响应时间指标设置时不应该使用平均响应时间作为指标而应该考虑使用目标时间的或者更大作为响应时间指标也就是说的用户客户端请求响应时间不会超过预设的目标值记住暂停时间只是一个目标并不能保证总是得到满足什么是转移失败对或进行时如果的区不足就会发生提升失败堆内存不能继续扩充因为已经达到最大值了当使用时将会在日志中显示空间溢出这是很昂贵的操作仍继续所以空间必须被释放拷贝失败的对象必须被放到正确的位置指向区域中的任何更新都必须重新生成所有这些步骤都是代价高昂的如何避免转移失败要避免避免转移失败考虑采纳下列选项增加堆内存大小增加其默认值是创建了一个假天花板在需要更大的情况下会尝试从保留内存获取更早启动标记周期通过采用选项增加标记线程的数量的参数完全列表下面是完整的的开关参数列表在使用时请记住上面所述的最佳实践选项默认值说明使用垃圾收集器设置最大停顿时间指标这是一个软性指标会尽量去达成这个目标启动并发周期时的堆内存占用百分比之类的垃圾收集器用它来触发并发周期基于整个堆的使用率而不只是某一代内存的使用比值为则表示一直执行循环默认值为新生代与老生代的大小比例默认值为空间大小的比例默认值为提升年老代的最大临界值默认值为设置垃圾收集器在并行阶段使用的线程数默认值随运行的平台不同而不同并发垃圾收集器使用的线程数量默认值随运行的平台不同而不同设置堆内存保留为假天花板的总量以降低提升失败的可能性默认值是使用时堆会被分为大小统一的的区此参数可以指定每个区的大小默认值将根据算出最优解最小值为最大值为记录的日志记录的日志我们要介绍的最后一个主题是使用日志信息来分享收集器的性能本节简要介绍垃圾收集的相关参数以及日志中打印的相关信息设置日志细节可以设置种不同的日志级别等价于设置日志级别为好日志输出示例设置日志级别为更好使用此选项会显示以下信息每个阶段的以及时间根扫描更新同时处理缓冲区信息扫描对象拷贝终止包括尝试次数还显示执行时间比如选择引用处理引用排队以及释放等显示以及总的占用信息日志输出示例设置日志级别为最好和级别类似包含每个线程信息有两个参数决定了日志中打印的时间显示形式显示从启动时算起的运行时间日志输出示例在每条记录前加上日期时间日志输出示例理解日志为了使你更好地理解日志本节通过实际的日志输出定义了许多专业术语下面的例子显示了日志的内容并加上日志中出现的术语和值的解释说明更多信息请参考的博客垃圾回收日志日志相关术语并行阶段耗时主要并行部分运行停顿的整体时间各个工作线程启动时的时间戳日志是根据排序并且每条记录都是一致的外部根扫描扫描外部根花费的时间如指向堆内存的系统词典等部分更新必须更新在之前已经完成但尚未处理的缓冲花费的时间取决于的密度越多耗费的时间就越长扫描查找指向的指针对象拷贝每个独立的线程在拷贝和转移对象时所消耗的时间结束时间当线程完成了自己那部分对象的复制和扫描就进入终止协议它查找未完成的工作一旦它完成就会再进入终止协议终止尝试记录所有查找工作的尝试次数独立的停止时的时间戳每个独立的线程消耗的时间每个线程中不能归属到之前列出的阶段的其他时间这个值应该很低过去我们见过很高的值是由于的其他部分的瓶颈引起的例如在分层代码缓存占有率的增加清除扫描元数据的消耗的时间其他各种暂停的连续阶段花费的时间敲定要进行垃圾回收的集合时消耗的时间通常很小在必须选择区时会稍微长一点点处理等引用所花费的时间不同于前面的阶段将等引用放置到待处理列表花费的时间释放刚被垃圾收集的区所消耗的时间包括对应的总结在此中您对中的垃圾收集器有了个大致的了解首先你学到了为何堆和垃圾收集器是所有的关键部分接下来讲述了使用和收集器进行垃圾回收的工作方式接下来您了解了的命令行参数开关以及和使用它们的最佳实践最后您了解了日志对象以及日志中的数据在本教程中你学到了这些知识的组成部分对的概述概述垃圾收集器概述垃圾收集器命令行参数与最佳实践的日志信息相关资源更多相关信息请参考以下网站链接虚拟机参数垃圾优先收集器的博客垃圾回收日志开发富客户端应用程序性能优化权威指南中文版学习资料库",isPost:!0,isHome:!1,isHighlightShrink:!0,isToc:!0,postUpdate:"2019-01-24 18:27:18",postMainColor:""}</script><noscript><style>#nav{opacity:1}.justified-gallery img{opacity:1}#post-meta time,#recent-posts time{display:inline!important}</style></noscript><script>(e=>{e.saveToLocal={set:(e,t,a)=>{var o;0!==a&&(o=Date.now(),localStorage.setItem(e,JSON.stringify({value:t,expiry:o+864e5*a})))},get:e=>{var t=localStorage.getItem(e);if(t){t=JSON.parse(t);if(!(Date.now()>t.expiry))return t.value;localStorage.removeItem(e)}}},e.getScript=(o,c={})=>new Promise((t,e)=>{const a=document.createElement("script");a.src=o,a.async=!0,a.onerror=e,a.onload=a.onreadystatechange=function(){var e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(a.onload=a.onreadystatechange=null,t())},Object.keys(c).forEach(e=>{a.setAttribute(e,c[e])}),document.head.appendChild(a)}),e.getCSS=(o,c=!1)=>new Promise((t,e)=>{const a=document.createElement("link");a.rel="stylesheet",a.href=o,c&&(a.id=c),a.onerror=e,a.onload=a.onreadystatechange=function(){var e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(a.onload=a.onreadystatechange=null,t())},document.head.appendChild(a)}),e.activateDarkMode=()=>{document.documentElement.setAttribute("data-theme","dark"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#0d0d0d")},e.activateLightMode=()=>{document.documentElement.setAttribute("data-theme","light"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#ffffff")};var e=saveToLocal.get("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches,a=window.matchMedia("(prefers-color-scheme: light)").matches,o=window.matchMedia("(prefers-color-scheme: no-preference)").matches,c=!t&&!a&&!o,t=(void 0===e?(a?activateLightMode():t?activateDarkMode():(o||c)&&((a=(new Date).getHours())<=6||18<=a?activateDarkMode:activateLightMode)(),window.matchMedia("(prefers-color-scheme: dark)").addListener(e=>{void 0===saveToLocal.get("theme")&&(e.matches?activateDarkMode:activateLightMode)()})):("light"===e?activateLightMode:activateDarkMode)(),saveToLocal.get("aside-status"));void 0!==t&&("hide"===t?document.documentElement.classList.add("hide-aside"):document.documentElement.classList.remove("hide-aside"));/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)&&document.documentElement.classList.add("apple")})(window)</script><link rel="stylesheet" href="/css/1.min.css?1" media="async" onload='this.media="all"'><link rel="stylesheet" href="/css/bg.css?1" media="async" onload='this.media="all"'><meta name="generator" content="Hexo 6.3.0"><link rel="alternate" href="/atom.xml" title="云少IT" type="application/atom+xml"><link rel="alternate" href="/rss.xml" title="云少IT" type="application/rss+xml"></head><body data-type="anzhiyu"><div id="web_bg"></div><div id="an_music_bg"></div><link rel="stylesheet" href="https://cdn.cbd.int/anzhiyu-theme-static@1.1.10/progress_bar/progress_bar.css"><script async src="https://cdn.cbd.int/pace-js@1.2.4/pace.min.js" data-pace-options="{ &quot;restartOnRequestAfter&quot;:false,&quot;eventLag&quot;:false}"></script><div class="post" id="body-wrap"><header class="post-bg" id="page-header"><nav id="nav"><div id="nav-group"><span id="blog_name"><div class="back-home-button"><i class="anzhiyufont anzhiyu-icon-grip-vertical"></i><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">网页</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top/" title="博客"><img class="back-menu-item-icon" src="/img/favicon.ico" alt="博客"><span class="back-menu-item-text">博客</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top" title="图床"><img class="back-menu-item-icon" src="https://www.tryrun.top/favicon.ico" alt="图床"><span class="back-menu-item-text">图床</span></a></div></div></div></div><a id="site-name" href="/" accesskey="h"><div class="title">云少IT</div><i class="anzhiyufont anzhiyu-icon-house-chimney"></i></a></span><div class="mask-name-container"><div id="name-container"><a id="page-name" href="javascript:anzhiyu.scrollToDest(0, 500)" rel="external nofollow noreferrer">PAGE_NAME</a></div></div><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>望四方</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="anzhiyufont anzhiyu-icon-box-archive faa-tada" style="font-size:.9em"></i><span> 归名档</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="anzhiyufont anzhiyu-icon-shapes faa-tada" style="font-size:.9em"></i><span> 归四类</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="anzhiyufont anzhiyu-icon-tags faa-tada" style="font-size:.9em"></i><span> 书中签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/charts/"><i class="fa-fw fas fa-chart-bar faa-tada"></i><span> 统计</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>友链</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="anzhiyufont anzhiyu-icon-link faa-tada" style="font-size:.9em"></i><span> 四方好友</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="anzhiyufont anzhiyu-icon-artstation faa-tada" style="font-size:.9em"></i><span> 朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/comments/"><i class="anzhiyufont anzhiyu-icon-envelope faa-tada" style="font-size:.9em"></i><span> 留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>我的</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/bangumis/"><i class="anzhiyufont anzhiyu-icon-bilibili faa-tada" style="font-size:.9em"></i><span> 追番页</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/album/"><i class="anzhiyufont anzhiyu-icon-images faa-tada" style="font-size:.9em"></i><span> 刹那间</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/equipment/"><i class="fas fa-heart faa-tada"></i><span> 我的装备</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/collect/"><i class="fas fa-camcorder faa-tada"></i><span> 观影阁</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>关于</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="anzhiyufont anzhiyu-icon-paper-plane faa-tada" style="font-size:.9em"></i><span> 关于本人</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="anzhiyufont anzhiyu-icon-lightbulb faa-tada" style="font-size:.9em"></i><span> 闲言碎语</span></a></li><li><a class="site-page child faa-parent animated-hover" href="javascript:toRandomPost()" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-shoe-prints1 faa-tada" style="font-size:.9em"></i><span> 随便逛逛</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/disclaimer/"><i class="fas fa-heart faa-tada"></i><span> 免责声明</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/love/"><i class="anzhiyufont anzhiyu-icon-heartbeat faa-tada" style="font-size:.9em"></i><span> 恋爱小屋</span></a></li></ul></div></div></div><div id="nav-right"><div class="nav-button only-home" id="travellings_button" title="随机前往一个开往项目网站"><a class="site-page" onclick="anzhiyu.totraveling()" title="随机前往一个开往项目网站" href="javascript:void(0);" rel="external nofollow" data-pjax-state="external"><i class="anzhiyufont anzhiyu-icon-train"></i></a></div><div class="nav-button" id="randomPost_button"><a class="site-page" onclick="toRandomPost()" title="随机前往一个文章" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-dice"></i></a></div><div class="nav-button" id="search-button"><a class="site-page social-icon search" href="javascript:void(0);" rel="external nofollow noreferrer" title="搜索🔍" accesskey="s"><i class="anzhiyufont anzhiyu-icon-magnifying-glass"></i><span> 搜索</span></a></div><input id="center-console" type="checkbox"><label class="widget" for="center-console" title="中控台" onclick="anzhiyu.switchConsole()"><i class="left"></i><i class="widget center"></i><i class="widget right"></i></label><div id="console"><div class="console-card-group-reward"><ul class="reward-all console-card"><li class="reward-item"><a href="/img/wxpay.webp" target="_blank"><img class="post-qr-code-img" alt="wechat" src="/img/wxpay.webp"></a><div class="post-qr-code-desc">wechat</div></li><li class="reward-item"><a href="/img/alipay.webp" target="_blank"><img class="post-qr-code-img" alt="alipay" src="/img/alipay.webp"></a><div class="post-qr-code-desc">alipay</div></li></ul></div><div class="console-card-group"><div class="console-card-group-left"><div class="console-card" id="card-newest-comments"><div class="card-content"><div class="author-content-item-tips">互动</div><span class="author-content-item-title">最新评论</span></div><div class="aside-list"><span>正在加载中...</span></div></div></div><div class="console-card-group-right"><div class="console-card tags"><div class="card-content"><div class="author-content-item-tips">兴趣点</div><span class="author-content-item-title">寻找你感兴趣的领域</span><div class="card-tags"><div class="item-headline"></div><div class="card-tag-cloud"><a href="/tags/API/" style="font-size:1.05rem;color:#637571">API<sup>43</sup></a><a href="/tags/Base64/" style="font-size:1.05rem;color:#8a0460">Base64<sup>1</sup></a><a href="/tags/Collectors/" style="font-size:1.05rem;color:#6b3641">Collectors<sup>3</sup></a><a href="/tags/Date/" style="font-size:1.05rem;color:#5e6603">Date<sup>3</sup></a><a href="/tags/Executor/" style="font-size:1.05rem;color:#abb61f">Executor<sup>9</sup></a><a href="/tags/Guava/" style="font-size:1.05rem;color:#6dc55c">Guava<sup>1</sup></a><a href="/tags/JVM/" style="font-size:1.05rem;color:#8745c2">JVM<sup>8</sup></a><a href="/tags/Java8/" style="font-size:1.05rem;color:#804042">Java8<sup>21</sup></a><a href="/tags/Java9/" style="font-size:1.05rem;color:#21b4c6">Java9<sup>21</sup></a><a href="/tags/Java%E5%B9%B6%E5%8F%91/" style="font-size:1.05rem;color:#0a3988">Java并发<sup>20</sup></a><a href="/tags/Lambda/" style="font-size:1.05rem;color:#29446d">Lambda<sup>4</sup></a><a href="/tags/Lock/" style="font-size:1.05rem;color:#afc378">Lock<sup>1</sup></a><a href="/tags/Maven/" style="font-size:1.05rem;color:#b10843">Maven<sup>1</sup></a><a href="/tags/Memcached/" style="font-size:1.05rem;color:#9663a4">Memcached<sup>23</sup></a><a href="/tags/Mongodb/" style="font-size:1.05rem;color:#b4214d">Mongodb<sup>49</sup></a><a href="/tags/Queue/" style="font-size:1.05rem;color:#220f01">Queue<sup>1</sup></a><a href="/tags/Redis/" style="font-size:1.05rem;color:#c4106c">Redis<sup>27</sup></a><a href="/tags/Stream/" style="font-size:1.05rem;color:#1f5f9f">Stream<sup>4</sup></a><a href="/tags/Thread/" style="font-size:1.05rem;color:#c3563b">Thread<sup>7</sup></a><a href="/tags/Thread-pool/" style="font-size:1.05rem;color:#1a3364">Thread pool<sup>7</sup></a><a href="/tags/forkJoinPool/" style="font-size:1.05rem;color:#1ea132">forkJoinPool<sup>2</sup></a><a href="/tags/stream/" style="font-size:1.05rem;color:#a00679">stream<sup>1</sup></a><a href="/tags/%E4%B8%93%E6%A0%8F/" style="font-size:1.05rem;color:#9e5e9b">专栏<sup>35</sup></a><a href="/tags/%E4%BA%8B%E5%8A%A1/" style="font-size:1.05rem;color:#4d47bc">事务<sup>1</sup></a><a href="/tags/%E4%BC%98%E5%8C%96/" style="font-size:1.05rem;color:#a56245">优化<sup>1</sup></a><a href="/tags/%E5%91%BD%E4%BB%A4/" style="font-size:1.05rem;color:#9c8435">命令<sup>57</sup></a><a href="/tags/%E5%AE%89%E8%A3%85/" style="font-size:1.05rem;color:#647e28">安装<sup>6</sup></a><a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size:1.05rem;color:#a192b9">工具<sup>2</sup></a><a href="/tags/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" style="font-size:1.05rem;color:#22a370">数据类型<sup>8</sup></a><a href="/tags/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/" style="font-size:1.05rem;color:#6b985c">生命周期<sup>1</sup></a><a href="/tags/%E7%AE%80%E4%BB%8B/" style="font-size:1.05rem;color:#bc5f40">简介<sup>7</sup></a><a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size:1.05rem;color:#167366">算法<sup>10</sup></a><a href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" style="font-size:1.05rem;color:#aa928f">设计模式<sup>38</sup></a><a href="/tags/%E9%85%8D%E7%BD%AE/" style="font-size:1.05rem;color:#3a740b">配置<sup>2</sup></a><a href="/tags/%E9%9D%A2%E8%AF%95/" style="font-size:1.05rem;color:#75c343">面试<sup>11</sup></a></div></div><hr></div></div><div class="console-card history"><div class="item-headline"><i class="anzhiyufont anzhiyu-icon-box-archiv"></i><span>文章</span></div><div class="card-archives"><div class="item-headline"><i class="anzhiyufont anzhiyu-icon-archive"></i><span>归档</span><a class="card-more-btn" href="/archives/" title="查看更多"> <i class="anzhiyufont anzhiyu-icon-angle-right"></i></a></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2023/06/"><span class="card-archive-list-date">六月 2023</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">2</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2021/05/"><span class="card-archive-list-date">五月 2021</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">2</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/10/"><span class="card-archive-list-date">十月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">21</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/09/"><span class="card-archive-list-date">九月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">44</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/08/"><span class="card-archive-list-date">八月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">47</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/07/"><span class="card-archive-list-date">七月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">42</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/06/"><span class="card-archive-list-date">六月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">31</span><span>篇</span></div></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2020/05/"><span class="card-archive-list-date">五月 2020</span><div class="card-archive-list-count-group"><span class="card-archive-list-count">43</span><span>篇</span></div></a></li></ul></div><hr></div></div></div><div class="button-group"><div class="console-btn-item"><a class="darkmode_switchbutton" title="显示模式切换" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-moon"></i></a></div><div class="console-btn-item" id="consoleHideAside" onclick="anzhiyu.hideAsideBtn()" title="边栏显示控制"><a class="asideSwitch"><i class="anzhiyufont anzhiyu-icon-arrows-left-right"></i></a></div><div class="console-btn-item on" id="consoleCommentBarrage" onclick="anzhiyu.switchCommentBarrage()" title="热评开关"><a class="commentBarrage"><i class="anzhiyufont anzhiyu-icon-message"></i></a></div><div class="console-btn-item" id="consoleMusic" onclick="anzhiyu.musicToggle()" title="音乐开关"><a class="music-switch"><i class="anzhiyufont anzhiyu-icon-music"></i></a></div></div><div class="console-mask" onclick="anzhiyu.hideConsole()" href="javascript:void(0);" rel="external nofollow noreferrer"></div></div><div class="nav-button" id="nav-totop"><a class="totopbtn" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i><span id="percent" onclick="anzhiyu.scrollToDest(0,500)">0</span></a></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer" title="切换"><i class="anzhiyufont anzhiyu-icon-bars"></i></a></div></div></div></nav><div id="post-info"><div id="post-firstinfo"><div class="meta-firstline"><a class="post-meta-original">原创</a><span class="article-meta tags"><a class="article-meta__tags" href="/tags/JVM/" tabindex="-1" itemprop="url"> <span><i class="anzhiyufont anzhiyu-icon-hashtag"></i>JVM</span></a></span></div></div><h1 class="post-title" itemprop="name headline">一、GC 性能优化 – G1垃圾收集器入门</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="anzhiyufont anzhiyu-icon-calendar-days post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" itemprop="dateCreated datePublished" datetime="2019-01-24T10:27:18.000Z" title="发表于 2019-01-24 18:27:18">2019-01-24</time><span class="post-meta-separator"></span><i class="anzhiyufont anzhiyu-icon-history post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" itemprop="dateCreated datePublished" datetime="2019-01-24T10:27:18.000Z" title="更新于 2019-01-24 18:27:18">2019-01-24</time></span></div><div class="meta-secondline"><span class="post-meta-separator"></span><span class="post-meta-wordcount"><i class="anzhiyufont anzhiyu-icon-file-word post-meta-icon" title="文章字数"></i><span class="post-meta-label" title="文章字数">字数总计:</span><span class="word-count" title="文章字数">10k</span><span class="post-meta-separator"></span><i class="anzhiyufont anzhiyu-icon-clock post-meta-icon" title="阅读时长"></i><span class="post-meta-label" title="阅读时长">阅读时长:</span><span>34分钟</span></span><span class="post-meta-separator"></span><span class="post-meta-pv-cv" data-flag-title="一、GC 性能优化 – G1垃圾收集器入门"><i class="anzhiyufont anzhiyu-icon-fw-eye post-meta-icon"></i><span class="post-meta-label" title="阅读量">阅读量:</span><span id="busuanzi_value_page_pv"><i class="anzhiyufont anzhiyu-icon-spinner anzhiyu-spin"></i></span></span><span class="post-meta-separator"> </span><span class="post-meta-position" title="作者IP属地为武汉"><i class="anzhiyufont anzhiyu-icon-location-dot"></i>武汉</span></div></div></div><section class="main-hero-waves-area waves-area"><svg class="waves-svg" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z"></path></defs><g class="parallax"><use href="#gentle-wave" x="48" y="0"></use><use href="#gentle-wave" x="48" y="3"></use><use href="#gentle-wave" x="48" y="5"></use><use href="#gentle-wave" x="48" y="7"></use></g></svg></section><div id="post-top-cover"><img class="nolazyload" id="post-top-bg" src="https://cn.bing.com/th?id=OHR.FanalMadeira_EN-US8481108715_UHD.jpg"></div></header><main id="blog-container"><div class="layout" id="content-inner"><div id="post"><div class="post-ai-description"><div class="ai-title"><i class="anzhiyufont anzhiyu-icon-bilibili"></i><div class="ai-title-text">AI-摘要</div><i class="anzhiyufont anzhiyu-icon-arrow-rotate-right"></i><i class="anzhiyufont anzhiyu-icon-circle-dot" title="朗读摘要"></i><div id="ai-tag">Tianli GPT</div></div><div class="ai-explanation">AI初始化中...</div><div class="ai-btn-box"><div class="ai-btn-item">介绍自己 🙈</div><div class="ai-btn-item">生成本文简介 👋</div><div class="ai-btn-item">推荐相关文章 📖</div><div class="ai-btn-item">前往主页 🏠</div><div class="ai-btn-item" id="go-tianli-blog">前往爱发电购买</div></div><script data-pjax src="/js/anzhiyu/ai_abstract.js"></script></div><article class="post-content" id="article-container" itemscope itemtype="https://it985.github.io/posts/5333e17a.html"><header><a href="/tags/JVM/" tabindex="-1" itemprop="url">JVM</a><h1 id="CrawlerTitle" itemprop="name headline">一、GC 性能优化 – G1垃圾收集器入门</h1><span itemprop="author" itemscope itemtype="http://schema.org/Person">云少</span><time itemprop="dateCreated datePublished" datetime="2019-01-24T10:27:18.000Z" title="发表于 2019-01-24 18:27:18">2019-01-24</time><time itemprop="dateCreated datePublished" datetime="2019-01-24T10:27:18.000Z" title="更新于 2019-01-24 18:27:18">2019-01-24</time></header><h1 id="一、GC-性能优化-–-G1垃圾收集器入门"><a href="#一、GC-性能优化-–-G1垃圾收集器入门" class="headerlink" title="一、GC 性能优化 – G1垃圾收集器入门"></a>一、GC 性能优化 – G1垃圾收集器入门</h1><h1 id="G1垃圾收集器入门"><a href="#G1垃圾收集器入门" class="headerlink" title="G1垃圾收集器入门"></a>G1垃圾收集器入门</h1><blockquote><p>master ，这是我的<a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top/">小站</a>,欢迎访问哦~~</p></blockquote><h2 id="说明"><a href="#说明" class="headerlink" title="说明"></a>说明</h2><p>concurrent: 并发, 多个线程协同做同一件事情(有状态)</p><p>parallel: 并行, 多个线程各做各的事情(互相间无共享状态)</p><p><strong>在GC领域</strong>: concurrent算法指GC线程和业务线程能并发执行； parallel指GC线程之间的并行。</p><p>参考: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html">What’s the difference between concurrency and parallelism</a></p><h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><p>目的</p><p>本文介绍如何使用G1,及在 Hotspot JVM 中怎么使用G1垃圾收集器。 您将了解 G1 收集器的内部原理, 切换为 G1 收集器的命令行参数, 以及让其记录GC日志的选项。</p><p>需要的时间</p><p>大约 1 个小时</p><p>简介</p><p>本文涵盖了Java虚拟机(JVM, Java Virtual Machine)中 G1 的基础知识。</p><p>1、第一部分, 简单概述JVM的同时介绍了垃圾收集和性能.</p><p>2、接下来讲述了 Hotspot JVM 中 CMS 收集器是如何工作的.</p><p>3、接着再一步一步地指导在 Hotspot JVM 中使用G1进行垃圾回收的工作方式.</p><p>4、之后的一个小节介绍 G1 垃圾收集器可用的命令行参数.</p><p>5、最后,您将了解如何配置使G1收集器记录日志.</p><p>硬件与软件环境需求</p><p>下面是 硬件与软件环境需求 清单:</p><ul><li>一台PC机, 运行 Windows XP 以上操作系统, Mac OS X 或者 Linux 都可以. 注意,因为作者在Windows 7上进行开发和测试, 尚未在所有平台上完成测试。 但在 OS X和Linux 上应该也是正常的。最好配置了多核CPU.</li><li>Java 7 Update 9 或更高版本</li><li>最新的 Java 7 Demos and Samples Zip 文件</li></ul><p>准备条件</p><p>在开始学习本教程之前, 你需要:</p><ul><li>下载并安装最新的 Java JDK (JDK 7 u9 或 以后的版本): <a target="_blank" rel="noopener external nofollow noreferrer" href="http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html">Java 7 JDK 下载页面</a></li><li>下载并安装 Demos and Samples (示例与样例) zip 文件, 下载页面和JDK相同. 然后解压到合适的位置. 如:<code>C:\javademos</code></li></ul><h2 id="Java-技术-和-JVM"><a href="#Java-技术-和-JVM" class="headerlink" title="Java 技术 和 JVM"></a>Java 技术 和 JVM</h2><h3 id="Java-概述"><a href="#Java-概述" class="headerlink" title="Java 概述"></a>Java 概述</h3><p>Java 是 Sun Microsystems 公司在1995年发布的一门编程语言. 同时也是一个运行Java程序的底层平台. 提供工具、游戏和企业应用程序支持。Java 运行在全世界超过8.5亿的PC,以及数十亿的智能设备上,包括 mobile 和 TV. Java 是由许多关键部件组成的一个整体, 统称为Java平台。</p><p>JRE(Java Runtime Edition)</p><p>一般来说下载了Java以后, 你就得到了一个Java运行时: Java Runtime Environment (JRE). JRE 由Java虚拟机 Java Virtual Machine (JVM), Java 平台核心类(core classes), 以及 Java平台支持库组成. 必须有这三大组件的支持才能在你的电脑上运行 Java 程序. 例如 Java 7, 可以在操作系统上作为桌面应用程序运行, 还可以通过 Java Web Start 从Web上安装, 或者是作为嵌入式Web程序在浏览器中运行 (通过 JavaFX).</p><p>Java 编程语言</p><p>Java 是一门面向对象编程语言(object-oriented programming language), 包涵以下特性.</p><ul><li>Platform Independence – Java 应用程序被编译为字节码(bytecode)存放到 class 文件中, 由JVM加载. 因为程序在 JVM 中运行, 所以可以跨平台运行在各种操作系统&#x2F;设备上.</li><li>Object-Oriented – Java 是一门面向对象的语言, 继承了 C 和 C++ 的很多特性,并在此基础上进行扩充和优化.</li><li>Automatic Garbage Collection – Java对内存进行 自动分配(allocates) 和自动释放(deallocates). 所以程序不再执行这一繁琐的任务(其实自动内存回收,更多的好处是减少了编程需要重复处理的这种细节,另一个例子是对JDBC的封装).</li><li>Rich Standard Library – Java包含大量的标准对象,可以执行诸如输入输出(input&#x2F;output), 网络操作以及日期处理等任务.</li></ul><p>JDK(Java Development Kit)</p><p>JDK 是用来开发Java程序的一系列工具集. 通过JDK, 你可以编译用Java语言书写的程序, 并在 JVM 中运行. 另外, JDK 还提供了打包(packaging)和分发(distributing)程序的工具.</p><p>JDK 和 JRE 使用同样的 Java Application Programming Interfaces (<a target="_blank" rel="noopener external nofollow noreferrer" href="http://docs.oracle.com/javase/7/docs/api/">Java API</a>).Java API 是预先打包好以供程序员用来开发程序的类库集合. 通过 Java API 使得很多常规任务可以很轻松的就完成,如 字符串操作(string manipulation), 时间日期处理(date&#x2F;time processing), 网络编程(networking), 以及实现各种数据结构(data structures, 如 lists, maps, stacks, and queues).</p><p>JVM(Java Virtual Machine)</p><p>Java Virtual Machine (JVM) 是一台抽象的计算机(abstract computing machine). JVM 本质是一个程序, 但在运行于JVM上的程序看来, 他就像一台真实机器一样. 这样, Java程序就能使用相同的接口和库. 每种特定操作系统上的 JVM 实现, 都将 Java 程序指令转换为本地机器的指令(instructions)和命令(commands). 由此,实现了Java程序的平台独立性.</p><p>Java虚拟机的第一个原型实现,由 Sun Microsystems, Inc. 完成, 在一台手持设备上用软件模拟了 Java虚拟机指令集, 类似于今天的 PDA(Personal Digital Assistant). Oracle 当前在移动设备,桌面系统和服务器上都提供了Java虚拟机实现, 但Java虚拟机不限制使用任何特定的技术,硬件,或操作系统。JVM也不一定都是基于软件的,你可以直接在硬件CPU上实现JVM指令, 还可以芯片上实现,或者采用 microcode 的方式来实现.</p><p>Java 虚拟机完全不关心Java语言的细节, 只识别 class 文件这种特定的二进制格式. 一个 class 文件包含 Java虚拟机指令(或称之为字节码 bytecode) 及符号变量表(symbol table), 还有一些辅助信息.</p><p>基于安全性考虑, Java虚拟机对 class 文件中的代码执行 强语法检查和组成结构规范限制. 既然虚拟机有这种特征, 那么任何一门编程语言,只要能编译为合法的 class 文件，都可以加载到 Java虚拟机 里面执行。由于具有通用性,跨平台特性, 其他语言的实现者可以把Java虚拟机作为该语言的加载执行工具。(1) <a target="_blank" rel="noopener external nofollow noreferrer" href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-1.html">The Java Virtual Machine</a></p><h3 id="探索-JVM-体系架构"><a href="#探索-JVM-体系架构" class="headerlink" title="探索 JVM 体系架构"></a>探索 JVM 体系架构</h3><p>Hotspot 架构</p><p>HotSpot JVM 有一个稳定强悍的架构, 支持强大的功能与特性, 具备实现高性能和大规模可伸缩性的能力。例如,HotSpot JVM JIT编译器能动态进行优化生成。换句话说,他们运行Java程序时,会针对底层系统架构动态生成高性能的本地机器指令。此外,通过成熟的演进和运行时环境的持续工程,加上多线程垃圾收集器,HotSpot JVM即使实在大型计算机系统上也能获得很高的伸缩性.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/52979516d53f8bc8.png" alt="img_1.png"></p><p>JVM 的主要组件包括: 类加载器(class loader), 运行时数据区(runtime data areas), 以及执行引擎(execution engine).</p><p>Hotspot 关键部分</p><p>与性能(performance)有关的部分是 JVM 最重要的组件,下图中用高亮的颜色来显示.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/700bf114275d1517.png" alt="img_2.png"></p><p>对JVM进行性能调优时有三大组件需要重点关注。堆(Heap)是存放对象的内存空间。这个区域由JVM启动时选择的垃圾收集器进行管理。大多数调优参数都是调整堆内存的大小,以及根据实际情况选择最合适的垃圾收集器. JIT编译器也对性能有很大的影响, 但新版本的JVM调优中很少需要关注.</p><h3 id="性能基础"><a href="#性能基础" class="headerlink" title="性能基础"></a>性能基础</h3><p>大多数情况下对 Java 程序进行调优, 主要关注两个目标之一: 响应速度(responsiveness) 和&#x2F;或 吞吐量(throughput). 下面的教程中我们将讲述这些概念.</p><p>响应能力(Responsiveness)</p><p>响应能力就是程序或系统对一个请求的响应有多迅速. 比如:</p><ul><li>程序UI响应速度有多灵敏</li><li>网站页面响应有多快</li><li>数据库查询有多快</li></ul><p>对响应速度要求很高的系统, 较大的停顿时间(large pause times) 是不可接受的. 重点是在非常短的时间周期内快速响应.</p><p>吞吐量(Throughput)</p><p>吞吐量关注在一个特定时间段内应用系统的最大工作量。衡量吞吐量的指标&#x2F;示例包括:</p><ul><li>给定时间内完成的事务数.</li><li>每小时批处理系统能完成的作业(jobs)数量.</li><li>每小时能完成多少次数据库查询</li></ul><p>在吞吐量方面优化的系统, 停顿时间长(High pause times)也是可以接受的。由于高吞吐量应用运行时间长,所以此时更关心的是如何尽可能快地完成整个任务，而不考虑快速响应。</p><h2 id="G1-垃圾收集器-Garbage-Collector"><a href="#G1-垃圾收集器-Garbage-Collector" class="headerlink" title="G1 垃圾收集器(Garbage Collector)"></a>G1 垃圾收集器(Garbage Collector)</h2><h3 id="G1-垃圾收集器"><a href="#G1-垃圾收集器" class="headerlink" title="G1 垃圾收集器"></a>G1 垃圾收集器</h3><p>G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征. 在Oracle JDK 7 update 4 及以上版本中得到完全支持, 专为以下应用程序设计:</p><ul><li>可以像CMS收集器一样,GC操作与应用的线程一起并发执行</li><li>紧凑的空闲内存区间且没有很长的GC停顿时间.</li><li>需要可预测的GC暂停耗时.</li><li>不想牺牲太多吞吐量性能.</li><li>启动后不需要请求更大的Java堆.</li></ul><p>G1的长期目标是取代CMS(Concurrent Mark-Sweep Collector, 并发标记-清除). 因为特性的不同使G1成为比CMS更好的解决方案. 一个区别是,G1是一款压缩型的收集器.G1通过有效的压缩完全避免了对细微空闲内存空间的分配,不用依赖于regions，这不仅大大简化了收集器，而且还消除了潜在的内存碎片问题。除压缩以外，G1的垃圾收集停顿也比CMS容易估计，也允许用户自定义所希望的停顿参数(pause targets)</p><p>G1 操作概述</p><p>上一代的垃圾收集器(串行serial, 并行parallel, 以及CMS)都把堆内存划分为固定大小的三个部分: 年轻代(young generation), 年老代(old generation), 以及持久代(permanent generation).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/3248b8326be5299c.png" alt="img_3.png"></p><p>内存中的每个对象都存放在这三个区域中的一个.</p><p>而 G1 收集器采用一种不同的方式来管理堆内存.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/f1cfae3effd48082.png" alt="img_4.png"></p><p>堆内存被划分为多个大小相等的 heap 区,每个heap区都是逻辑上连续的一段内存(virtual memory). 其中一部分区域被当成老一代收集器相同的角色(eden, survivor, old), 但每个角色的区域个数都不是固定的。这在内存使用上提供了更多的灵活性。</p><p>G1执行垃圾回收的处理方式与CMS相似. G1在全局标记阶段(global marking phase)并发执行, 以确定堆内存中哪些对象是存活的。标记阶段完成后,G1就可以知道哪些heap区的empty空间最大。它会首先回收这些区,通常会得到大量的自由空间. 这也是为什么这种垃圾收集方法叫做Garbage-First(垃圾优先)的原因。顾名思义, G1将精力集中放在可能布满可收回对象的区域, 可回收对象(reclaimable objects)也就是所谓的垃圾. G1使用暂停预测模型(pause prediction model)来达到用户定义的目标暂停时间,并根据目标暂停时间来选择此次进行垃圾回收的heap区域数量.</p><p>被G1标记为适合回收的heap区将使用转移(evacuation)的方式进行垃圾回收. G1将一个或多个heap区域中的对象拷贝到其他的单个区域中,并在此过程中压缩和释放内存. 在多核CPU上转移是并行执行的(parallel on multi-processors), 这样能减少停顿时间并增加吞吐量. 因此,每次垃圾收集时, G1都会持续不断地减少碎片, 并且在用户给定的暂停时间内执行. 这比以前的方法强大了很多. CMS垃圾收集器(Concurrent Mark Sweep,并发标记清理)不进行压缩. ParallelOld 垃圾收集只对整个堆执行压缩,从而导致相当长的暂停时间。</p><p>需要强调的是, G1并不是一款实时垃圾收集器(real-time collector). 能以极高的概率在设定的目标暂停时间内完成,但不保证绝对在这个时间内完成。 基于以前收集的各种监控数据, G1会根据用户指定的目标时间来预估能回收多少个heap区. 因此,收集器有一个相当精确的heap区耗时计算模型,并根据该模型来确定在给定时间内去回收哪些heap区.</p><p>注意 G1分为两个阶段: 并发阶段(concurrent, 与应用线程一起运行, 如: 细化 refinement、标记 marking、清理 cleanup) 和 并行阶段(parallel, 多线程执行, 如: 停止所有JVM线程, stop the world). 而 FullGC(完整垃圾收集)仍然是单线程的, 但如果进行适当的调优,则应用程序应该能够避免 full GC。</p><p>G1 的内存占用(Footprint)</p><p>如果从 ParallelOldGC 或者 CMS收集器迁移到 G1, 您可能会看到JVM进程占用更多的内存(a larger JVM process size). 这在很大程度上与 “accounting” 数据结构有关, 如 Remembered Sets 和 Collection Sets.</p><p>Remembered Sets 简称 RSets, 跟踪指向某个heap区内的对象引用. 堆内存中的每个区都有一个 RSet. RSet 使heap区能并行独立地进行垃圾集合. RSets的总体影响小于5%.</p><p>Collection Sets 简称 CSets, 收集集合, 在一次GC中将执行垃圾回收的heap区. GC时在CSet中的所有存活数据(live data)都会被转移(复制&#x2F;移动). 集合中的heap区可以是 Eden, survivor, 和&#x2F;或 old generation. CSets所占用的JVM内存小于1%.</p><p>推荐使用 G1 的场景(Recommended Use Cases)</p><p>G1的首要目标是为需要大量内存的系统提供一个保证GC低延迟的解决方案. 也就是说堆内存在6GB及以上,稳定和可预测的暂停时间小于0.5秒.</p><p>如果应用程序具有如下的一个或多个特征,那么将垃圾收集器从CMS或ParallelOldGC切换到G1将会大大提升性能.</p><ul><li>Full GC 次数太频繁或者消耗时间太长.</li><li>对象分配的频率或代数提升(promotion)显著变化.</li><li>受够了太长的垃圾回收或内存整理时间(超过0.5~1秒)</li></ul><p>注意: 如果正在使用CMS或ParallelOldGC,而应用程序的垃圾收集停顿时间并不长,那么继续使用现在的垃圾收集器是个好主意. 使用最新的JDK时并不要求切换到G1收集器。</p><h2 id="CMS的GC概述"><a href="#CMS的GC概述" class="headerlink" title="CMS的GC概述"></a>CMS的GC概述</h2><h3 id="分代GC-Generational-GC-与-CMS"><a href="#分代GC-Generational-GC-与-CMS" class="headerlink" title="分代GC(Generational GC)与 CMS"></a>分代GC(Generational GC)与 CMS</h3><p>并发标记清理(CMS, Concurrent Mark Sweep)收集器(也称为多并发低暂停的收集器)回收老年代内存(tenured generation). 它将垃圾回收中的绝大部分工作与应用程序的线程一起并发执行,以期能最小化暂停时间. 通常多并发低暂停收集器收集器不复制或也不压缩存活的对象. 垃圾回收不移动存活的对象, 如果产生内存碎片问题,就会分配&#x2F;占用更大的堆内存空间。</p><p>注意: 年轻代使用的CMS收集器也和并行收集器采用一样的算法.</p><p>CMS 垃圾收集阶段划分(Collection Phases)</p><p>CMS收集器在老年代堆内存的回收中执行分为以下阶段:</p><table><thead><tr><th align="center">阶段</th><th align="center">说明</th></tr></thead><tbody><tr><td align="center">(1) 初始标记 (Initial Mark)</td><td align="center">(Stop the World Event,所有应用线程暂停) 在老年代(old generation)中的对象, 如果从年轻代(young generation)中能访问到, 则被 “标记,marked” 为可达的(reachable).对象在旧一代“标志”可以包括这些对象可能可以从年轻一代。暂停时间一般持续时间较短,相对小的收集暂停时间.</td></tr><tr><td align="center">(2) 并发标记 (Concurrent Marking)</td><td align="center">在Java应用程序线程运行的同时遍历老年代(tenured generation)的可达对象图。扫描从被标记的对象开始,直到遍历完从root可达的所有对象. 调整器(mutators)在并发阶段的2、3、5阶段执行,在这些阶段中新分配的所有对象(包括被提升的对象)都立刻标记为存活状态.</td></tr><tr><td align="center">(3) 再次标记(Remark)</td><td align="center">(Stop the World Event, 所有应用线程暂停) 查找在并发标记阶段漏过的对象，这些对象是在并发收集器完成对象跟踪之后由应用线程更新的.</td></tr><tr><td align="center">(4) 并发清理(Concurrent Sweep)</td><td align="center">回收在标记阶段(marking phases)确定为不可及的对象. 死对象的回收将此对象占用的空间增加到一个空闲列表(free list),供以后的分配使用。死对象的合并可能在此时发生. 请注意,存活的对象并没有被移动.</td></tr><tr><td align="center">(5) 重置(Resetting)</td><td align="center">清理数据结构,为下一个并发收集做准备.</td></tr></tbody></table><p>CMS的GC步骤</p><p>接下来,让我们一步步地讲述CMS收集器的操作.</p><p>1、 CMS的堆内存结构(Heap Structure)</p><p>堆内存被分为3个空间.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/8148bdee4a90d357.png" alt="img_5.png"></p><p>年轻代(Young generation)分为 1个新生代空间(Eden)和2个存活区(survivor spaces). 老年代(Old generation)是一大块连续的空间, 垃圾回收(Object collection)就地解决(is done in place), 除了 Full GC, 否则不会进行压缩(compaction).</p><p>2、 CMS年轻代(Young) GC 的工作方式</p><p>年轻代(young generation)用高亮的绿色表示, 老年代(old generation)用蓝色表示。如果程序运行了一段时间,那么 CMS 看起来就像下图这个样子. 对象散落在老年代中的各处地方.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/192726af0cbf83ef.png" alt="img_6.png"></p><p>在使用 CMS 时, 老年代的对象回收就地进行(deallocated in place). 他们不会被移动到其他地方. 除了 Full GC, 否则内存空间不会进行压缩.</p><p>3、 年轻代垃圾回收(Young Generation Collection)</p><p>Eden区和survivor区中的存活对象被拷贝到另一个空的survivor 区. 存活时间更长,达到阀值的对象会被提升到老年代(promoted to old generation).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/fa0d88b11c0b3062.png" alt="img_7.png"></p><p>4、 年轻代(Young) GC 之后</p><p>年轻代(Young)进行一次垃圾回收之后, Eden 区被清理干净(cleared),两个 survivor 区中的一个也被清理干净了. 如下图所示:</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/467758bb9c7e4632.png" alt="img_8.png"></p><p>图中新提升的对象用深蓝色来标识. 绿色的部分是年轻代中存活的对象,但还没被提升到老年代中.</p><p>5、 CMS的老年代回收(Old Generation Collection)</p><p>两次stop the world事件发生在: 初始标记(initial mark)以及重新标记(remark)阶段. 当老年代达到一定的占有率时,CMS垃圾回收器就开始工作.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/250642f5cbf69ebb.png" alt="img_9.png"></p><p>(1) 初始标记(Initial mark)阶段的停顿时间很短,在此阶段存活的(live,reachable,可及的) 对象被记下来. (2) 并发标记(Concurrent marking)在程序继续运行的同时找出存活的对象. 最后, 在第(3)阶段(remark phase), 查找在第(2)阶段(concurrent marking)中错过的对象.</p><p>6、 老年代回收 – 并发清理(Concurrent Sweep)</p><p>在前面阶段未被标记的对象将会就地释放(deallocated in place). 此处没有压缩(compaction).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/cc6d9e73ea97deb5.png" alt="img_10.png"></p><p>备注: 未标记(Unmarked)的对象 &#x3D;&#x3D; 已死对象(Dead Objects)</p><p>7、 老年代回收 – 清理之后(After Sweeping)</p><p>在第(4)步(Sweeping phase)之后, 可以看到很多内存被释放了. 还应该注意到,这里并没有执行内存压缩整理(no compaction).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/a171766e38704784.png" alt="img_11.png"></p><p>最后, CMS 收集器进入(move through)第(5)阶段, 重置(resetting phase), 然后等候下一次的GC阀值到来(GC threshold).</p><h2 id="G1垃圾收集器概述"><a href="#G1垃圾收集器概述" class="headerlink" title="G1垃圾收集器概述"></a>G1垃圾收集器概述</h2><h3 id="一步步介绍G1"><a href="#一步步介绍G1" class="headerlink" title="一步步介绍G1"></a>一步步介绍G1</h3><p>G1收集器采用一种不同的方式来分配堆. 下面通过图解的方式一步步地讲述G1系统.</p><p>1、 G1的堆内存结构</p><p>堆内存被划分为固定大小的多个区域.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/19c77cd3ea35ab22.png" alt="img_12.png"></p><p>每个heap区(Region)的大小在JVM启动时就确定了. JVM 通常生成 2000 个左右的heap区, 根据堆内存的总大小,区的size范围允许为 1Mb 到 32Mb.</p><p>2、 G1 堆空间分配</p><p>实际上,这些区域(regions)被映射为逻辑上的 Eden, Survivor, 和 old generation(老年代)空间.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/f1cfae3effd48082.png" alt="img_13.png"></p><p>图中的颜色标识了每一个区域属于哪个角色. 存活的对象从一块区域转移(复制或移动)到另一块区域。设计成 heap 区的目的是为了并行地进行垃圾回收(的同时停止&#x2F;或不停止其他应用程序线程).</p><p>如图所示,heap区可以分配为 Eden, Survivor, 或 old generation(老年代)区. 此外,还有第四种类型的对象被称为巨无霸区域(Humongous regions),这种巨无霸区是设计了用来保存比<strong>标准块</strong>(standard region)大50%及以上的对象, 它们存储在一组连续的区中. 最后一个类型是堆内存中的未使用区(unused areas).</p><p>备注: 截止英文原文发表时,巨无霸对象的回收还没有得到优化. 因此,您应该尽量避免创建太大(大于32MB?)的对象.</p><p>3、 G1中的年轻代(Young Generation)</p><p>堆被分为大约2000个区. 最小size为1 Mb, 最大size为 32Mb. 蓝色的区保存老年代对象,绿色区域保存年轻代对象.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/9faf4372aa5f6d22.png" alt="img_14.png"></p><p>注意G1中各代的heap区不像老一代垃圾收集器一样要求各部分是连续的.</p><p>4、 G1中的一次年轻代GC</p><p>存活的对象被转移(copied or moved)到一个&#x2F;或多个存活区(survivor regions). 如果存活时间达到阀值,这部分对象就会被提升到老年代(promoted to old generation regions).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/e94d69be2fc128d0.png" alt="img_15.png"></p><p>此时会有一次 stop the world(STW)暂停. 会计算出 Eden大小和 survivor 大小,给下一次年轻代GC使用. 清单统计信息(Accounting)保存了用来辅助计算size. 诸如暂停时间目标之类的东西也会纳入考虑.</p><p>这种方法使得调整各代区域的尺寸很容易, 让其更大或更小一些以满足需要.</p><p>5、 G1的一次年轻代GC完成后</p><p>存活对象被转移到存活区(survivor regions) 或 老年代(old generation regions).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/b368e563d9db5a00.png" alt="img_16.png"></p><p>刚刚被提升上来的对象用深绿色显示. Survivor 区用绿色表示.</p><p>总结起来,G1的年轻代收集归纳如下:</p><ul><li>堆一整块内存空间,被分为多个heap区(regions).</li><li>年轻代内存由一组不连续的heap区组成. 这使得在需要时很容易进行容量调整.</li><li>年轻代的垃圾收集,或者叫 young GCs, 会有 stop the world 事件. 在操作时所有的应用程序线程都会被暂停(stopped).</li><li>年轻代 GC 通过多线程并行进行.</li><li>存活的对象被拷贝到新的 survivor 区或者老年代.</li></ul><h3 id="Old-Generation-Collection-with-G1"><a href="#Old-Generation-Collection-with-G1" class="headerlink" title="Old Generation Collection with G1"></a>Old Generation Collection with G1</h3><p>和 CMS 收集器相似, G1 收集器也被设计为用来对老年代的对象进行低延迟(low pause)的垃圾收集. 下表描述了G1收集器在老年代进行垃圾回收的各个阶段.</p><p>G1 收集阶段 – 并发标记周期阶段(Concurrent Marking Cycle Phases)</p><p>G1 收集器在老年代堆内存中执行下面的这些阶段. 注意有些阶段也是年轻代垃圾收集的一部分.</p><table><thead><tr><th align="center">阶段</th><th align="center">说明</th></tr></thead><tbody><tr><td align="center">(1) 初始标记(Initial Mark)</td><td align="center">(Stop the World Event,所有应用线程暂停) 此时会有一次 stop the world(STW)暂停事件. 在G1中, 这附加在(piggybacked on)一次正常的年轻代GC. 标记可能有引用指向老年代对象的survivor区(根regions).</td></tr><tr><td align="center">(2) 扫描根区域(Root Region Scanning)</td><td align="center">扫描 survivor 区中引用到老年代的引用. 这个阶段应用程序的线程会继续运行. 在年轻代GC可能发生之前此阶段必须完成.</td></tr><tr><td align="center">(3) 并发标记(Concurrent Marking)</td><td align="center">在整个堆中查找活着的对象. 此阶段应用程序的线程正在运行. 此阶段可以被年轻代GC打断(interrupted).</td></tr><tr><td align="center">(4) 再次标记(Remark)</td><td align="center">(Stop the World Event,所有应用线程暂停) 完成堆内存中存活对象的标记. 使用一个叫做 snapshot-at-the-beginning(SATB, 起始快照)的算法, 该算法比CMS所使用的算法要快速的多.</td></tr><tr><td align="center">(5) 清理(Cleanup)</td><td align="center">(Stop the World Event,所有应用线程暂停,并发执行) 在存活对象和完全空闲的区域上执行统计(accounting). (Stop the world) 擦写 Remembered Sets. (Stop the world) 重置空heap区并将他们返还给空闲列表(free list). (Concurrent, 并发)</td></tr><tr><td align="center">(*) 拷贝(Copying)</td><td align="center">(Stop the World Event,所有应用线程暂停) 产生STW事件来转移或拷贝存活的对象到新的未使用的heap区(new unused regions). 只在年轻代发生时日志会记录为 <code>[GC pause (young)]</code>. 如果在年轻代和老年代一起执行则会被日志记录为 <code>[GC Pause (mixed)]</code>.</td></tr></tbody></table><p>G1老年代收集步骤</p><p>顺着定义的阶段,让我们看看G1收集器如何处理老年代(old generation).</p><p>6、 初始标记阶段(Initial Marking Phase)</p><p>存活对象的初始标记被固定在年轻代垃圾收集里面. 在日志中被记为 <code>GC pause (young)(inital-mark)</code>。</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/c815b9990c955aea.png" alt="img_17.png"></p><p>7、 并发标记阶段(Concurrent Marking Phase)</p><p>如果找到空的区域(如用红叉“X”标示的区域), 则会在 Remark 阶段立即移除. 当然,”清单(accounting)”信息决定了活跃度(liveness)的计算.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/2531bd13788a390b.png" alt="img_18.png"></p><p>8、 再次标记阶段(Remark Phase)</p><p>空的区域被移除并回收。现在计算所有区域的活跃度(Region liveness).</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/a7e002a991be8dbe.png" alt="img_19.png"></p><p>9、 拷贝&#x2F;清理阶段(Copying&#x2F;Cleanup)</p><p>G1选择“活跃度(liveness)”最低的区域, 这些区域可以最快的完成回收. 然后这些区域和年轻代GC在同时被垃圾收集 . 在日志被标识为 <code>[GC pause (mixed)]</code>. 所以年轻代和老年代都在同一时间被垃圾收集.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/58d8adb7a80428ac.png" alt="img_20.png"></p><p>10、拷贝&#x2F;清理之后(After Copying&#x2F;Cleanup)</p><p>所选择的区域被收集和压缩到下图所示的深蓝色区域和深绿色区域.</p><p><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://s3.uuu.ovh/imgs/2022/05/07/7039e4f4b1b1207a.png" alt="img_21.png"></p><p>老年代GC(Old Generation GC)总结</p><p>总结下来,G1对老年代的GC有如下几个关键点:</p><ul><li>并发标记清理阶段(Concurrent Marking Phase)<ul><li>活跃度信息在程序运行的时候被并行计算出来</li><li>活跃度(liveness)信息标识出哪些区域在转移暂停期间最适合回收.</li><li>不像CMS一样有清理阶段(sweeping phase).</li></ul></li><li>再次标记阶段(Remark Phase)<ul><li>使用的 Snapshot-at-the-Beginning (SATB, 开始快照) 算法比起 CMS所用的算法要快得多.</li><li>完全空的区域直接被回收.</li></ul></li><li>拷贝&#x2F;清理阶段(Copying&#x2F;Cleanup Phase)<ul><li>年轻代与老年代同时进行回收.</li><li>老年代的选择基于其活跃度(liveness).</li></ul></li></ul><h2 id="命令行参数与最佳实践"><a href="#命令行参数与最佳实践" class="headerlink" title="命令行参数与最佳实践"></a>命令行参数与最佳实践</h2><h3 id="命令行参数与最佳实践-1"><a href="#命令行参数与最佳实践-1" class="headerlink" title="命令行参数与最佳实践"></a>命令行参数与最佳实践</h3><p>在本节中,让我们看看G1的各种命令行选项.</p><p>命令行基本参数</p><p>要启用 G1 收集器请使用: <code>-XX:+UseG1GC</code></p><p>下面是启动 Java2Demo示例程序的命令行示例. Java2Demo位于下载 JDK demos and samples 后解压的文件夹中:</p><p>java -Xmx50m -Xms50m -XX:+UseG1GC -XX:MaxGCPauseMillis&#x3D;200 -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar</p><p>关键命令行开关</p><p>-XX:+UseG1GC – 让 JVM 使用 G1 垃圾收集器.</p><p>-XX:MaxGCPauseMillis&#x3D;200 – 设置最大GC停顿时间(GC pause time)指标(target). 这是一个软性指标(soft goal), JVM 会尽力去达成这个目标. 所以有时候这个目标并不能达成. 默认值为 200 毫秒.</p><p>-XX:InitiatingHeapOccupancyPercent&#x3D;45 – 启动并发GC时的堆内存占用百分比. G1用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比例。值为 0 则表示“一直执行GC循环)’. 默认值为 45 (例如, 全部的 45% 或者使用了45%).</p><p>最佳实践</p><p>在使用 G1 作为垃圾收集器时,你应该遵循下面这些最佳实践的指导.</p><p>不要设置年轻代的大小(Young Generation Size)</p><p>假若通过 -Xmn 显式地指定了年轻代的大小, 则会干扰到 G1收集器的默认行为.</p><ul><li>G1在垃圾收集时将不再关心暂停时间指标. 所以从本质上说,设置年轻代的大小将禁用暂停时间目标.</li><li>G1在必要时也不能够增加或者缩小年轻代的空间. 因为大小是固定的,所以对更改大小无能为力.</li></ul><p>响应时间指标(Response Time Metrics)</p><p>设置 <code>XX:MaxGCPauseMillis=&lt;N&gt;</code> 时不应该使用平均响应时间(ART, average response time) 作为指标,而应该考虑使用目标时间的90%或者更大作为响应时间指标. 也就是说90%的用户(客户端&#x2F;?)请求响应时间不会超过预设的目标值. 记住,暂停时间只是一个目标,并不能保证总是得到满足.</p><p>什么是转移失败(Evacuation Failure)?</p><p>对 survivors 或 promoted objects 进行GC时如果JVM的heap区不足就会发生提升失败(promotion failure). 堆内存不能继续扩充,因为已经达到最大值了. 当使用 <code>-XX:+PrintGCDetails</code> 时将会在GC日志中显示 to-space overflow (to-空间溢出)。</p><p>这是很昂贵的操作!</p><ul><li>GC仍继续所以空间必须被释放.</li><li>拷贝失败的对象必须被放到正确的位置(tenured in place).</li><li>CSet指向区域中的任何 RSets 更新都必须重新生成(regenerated).</li><li>所有这些步骤都是代价高昂的.</li></ul><p>如何避免转移失败(Evacuation Failure)</p><p>要避免避免转移失败, 考虑采纳下列选项.</p><ul><li>增加堆内存大小<ul><li>增加 -XX:G1ReservePercent&#x3D;n, 其默认值是 10.</li><li>G1创建了一个假天花板(false ceiling),在需要更大 ‘to-space’ 的情况下会尝试从保留内存获取(leave the reserve memory free).</li></ul></li><li>更早启动标记周期(marking cycle)</li><li>通过采用 -XX:ConcGCThreads&#x3D;n 选项增加标记线程(marking threads)的数量.</li></ul><p>G1 的 GC 参数完全列表</p><p>下面是完整的 G1 的 GC 开关参数列表. 在使用时请记住上面所述的最佳实践.</p><table><thead><tr><th align="center">选项&#x2F;默认值</th><th align="center">说明</th></tr></thead><tbody><tr><td align="center">-XX:+UseG1GC</td><td align="center">使用 G1 (Garbage First) 垃圾收集器</td></tr><tr><td align="center">-XX:MaxGCPauseMillis&#x3D;n</td><td align="center">设置最大GC停顿时间(GC pause time)指标(target). 这是一个软性指标(soft goal), JVM 会尽量去达成这个目标.</td></tr><tr><td align="center">-XX:InitiatingHeapOccupancyPercent&#x3D;n</td><td align="center">启动并发GC周期时的堆内存占用百分比. G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示”一直执行GC循环”. 默认值为 45.</td></tr><tr><td align="center">-XX:NewRatio&#x3D;n</td><td align="center">新生代与老生代(new&#x2F;old generation)的大小比例(Ratio). 默认值为 2.</td></tr><tr><td align="center">-XX:SurvivorRatio&#x3D;n</td><td align="center">eden&#x2F;survivor 空间大小的比例(Ratio). 默认值为 8.</td></tr><tr><td align="center">-XX:MaxTenuringThreshold&#x3D;n</td><td align="center">提升年老代的最大临界值(tenuring threshold). 默认值为 15.</td></tr><tr><td align="center">-XX:ParallelGCThreads&#x3D;n</td><td align="center">设置垃圾收集器在并行阶段使用的线程数,默认值随JVM运行的平台不同而不同.</td></tr><tr><td align="center">-XX:ConcGCThreads&#x3D;n</td><td align="center">并发垃圾收集器使用的线程数量. 默认值随JVM运行的平台不同而不同.</td></tr><tr><td align="center">-XX:G1ReservePercent&#x3D;n</td><td align="center">设置堆内存保留为假天花板的总量,以降低提升失败的可能性. 默认值是 10.</td></tr><tr><td align="center">-XX:G1HeapRegionSize&#x3D;n</td><td align="center">使用G1时Java堆会被分为大小统一的的区(region)。此参数可以指定每个heap区的大小. 默认值将根据 heap size 算出最优解. 最小值为 1Mb, 最大值为 32Mb.</td></tr></tbody></table><h2 id="记录G1的GC日志"><a href="#记录G1的GC日志" class="headerlink" title="记录G1的GC日志"></a>记录G1的GC日志</h2><h3 id="记录G1的GC日志-1"><a href="#记录G1的GC日志-1" class="headerlink" title="记录G1的GC日志"></a>记录G1的GC日志</h3><p>我们要介绍的最后一个主题是使用日志信息来分享G1收集器的性能. 本节简要介绍垃圾收集的相关参数,以及日志中打印的相关信息.</p><p>设置日志细节(Log Detail)</p><p>可以设置3种不同的日志级别.</p><p>(1) -verbosegc (等价于 -XX:+PrintGC) 设置日志级别为 好 fine.</p><p>日志输出示例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[GC pause (G1 Humongous Allocation) (young) (initial-mark) 24M- &gt;21M(64M), 0.2349730 secs]</span><br><span class="line">[GC pause (G1 Evacuation Pause) (mixed) 66M-&gt;21M(236M), 0.1625268 secs]    </span><br></pre></td></tr></table></figure><p>(2) -XX:+PrintGCDetails 设置日志级别为 更好 finer. 使用此选项会显示以下信息:</p><ul><li>每个阶段的 Average, Min, 以及 Max 时间.</li><li>根扫描(Root Scan), RSet 更新(同时处理缓冲区信息), RSet扫描(Scan), 对象拷贝(Object Copy), 终止(Termination, 包括尝试次数).</li><li>还显示 “other” 执行时间, 比如选择 CSet, 引用处理(reference processing), 引用排队(reference enqueuing) 以及释放(freeing) CSet等.</li><li>显示 Eden, Survivors 以及总的 Heap 占用信息(occupancies).</li></ul><p>日志输出示例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[Ext Root Scanning (ms): Avg: 1.7 Min: 0.0 Max: 3.7 Diff: 3.7]</span><br><span class="line">[Eden: 818M(818M)-&gt;0B(714M) Survivors: 0B-&gt;104M Heap: 836M(4096M)-&gt;409M(4096M)]</span><br></pre></td></tr></table></figure><p>(3) -XX:+UnlockExperimentalVMOptions -XX:G1LogLevel&#x3D;finest 设置日志级别为 最好 finest. 和 finer 级别类似, 包含每个 worker 线程信息.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[Ext Root Scanning (ms): 2.1 2.4 2.0 0.0</span><br><span class="line">           Avg: 1.6 Min: 0.0 Max: 2.4 Diff: 2.3]</span><br><span class="line">       [Update RS (ms):  0.4  0.2  0.4  0.0</span><br><span class="line">           Avg: 0.2 Min: 0.0 Max: 0.4 Diff: 0.4]</span><br><span class="line">           [Processed Buffers : 5 1 10 0</span><br><span class="line">           Sum: 16, Avg: 4, Min: 0, Max: 10, Diff: 10]</span><br></pre></td></tr></table></figure><p>Determining Time</p><p>有两个参数决定了GC日志中打印的时间显示形式.</p><p>(1) -XX:+PrintGCTimeStamps – 显示从JVM启动时算起的运行时间.</p><p>日志输出示例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">1.729: [GC pause (young) 46M-&gt;35M(1332M), 0.0310029 secs]</span><br></pre></td></tr></table></figure><p>(2) -XX:+PrintGCDateStamps – 在每条记录前加上日期时间.</p><p>日志输出示例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">2022-05-07T11:16:32.057+0200: [GC pause (young) 46M-&gt;35M(1332M), 0.0317225 secs]</span><br></pre></td></tr></table></figure><p>理解 G1 日志</p><p>为了使你更好地理解GC日志, 本节通过实际的日志输出，定义了许多专业术语. 下面的例子显示了GC日志的内容,并加上日志中出现的术语和值的解释说明.</p><p>Note: 更多信息请参考 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://blogs.oracle.com/poonam/entry/understanding_g1_gc_logs">Poonam Bajaj的博客： G1垃圾回收日志</a>.</p><p>G1 日志相关术语</p><ul><li>Clear CT</li><li>CSet</li><li>External Root Scanning</li><li>Free CSet</li><li>GC Worker End</li><li>GC Worker Other</li><li>Object Copy</li><li>Other</li><li>Parallel Time</li><li>Ref Eng</li><li>Ref Proc</li><li>Scanning Remembered Sets</li><li>Termination Time</li><li>Update Remembered Set</li><li>Worker Start</li></ul><p>Parallel Time(并行阶段耗时)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">414.557: [GC pause (young), 0.03039600 secs] [Parallel Time: 22.9 ms]</span><br><span class="line">[GC Worker Start (ms): 7096.0 7096.0 7096.1 7096.1 706.1 7096.1 7096.1 7096.1 7096.2 7096.2 7096.2 7096.2</span><br><span class="line">       Avg: 7096.1, Min: 7096.0, Max: 7096.2, Diff: 0.2]</span><br></pre></td></tr></table></figure><p><code>Parallel Time</code> – 主要并行部分运行停顿的整体时间</p><p><code>Worker Start</code> – 各个工作线程(workers)启动时的时间戳(Timestamp)</p><p>Note: 日志是根据 thread id 排序,并且每条记录都是一致的.</p><p>External Root Scanning(外部根扫描)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[Ext Root Scanning (ms): 3.1 3.4 3.4 3.0 4.2 2.0 3.6 3.2 3.4 7.7 3.7 4.4</span><br><span class="line">     Avg: 3.8, Min: 2.0, Max: 7.7, Diff: 5.7]</span><br></pre></td></tr></table></figure><p><code>External root scanning</code> - 扫描外部根花费的时间(如指向堆内存的系统词典(system dictionary)等部分)</p><p>Update Remembered Set(更新 RSet)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[Update RS (ms): 0.1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 Avg: 0.0, Min: 0.0, Max: 0.1, Diff: 0.1]</span><br><span class="line">   [Processed Buffers : 26 0 0 0 0 0 0 0 0 0 0 0</span><br><span class="line">    Sum: 26, Avg: 2, Min: 0, Max: 26, Diff: 26]</span><br></pre></td></tr></table></figure><p><code>Update Remembered Set</code> - 必须更新在pause之前已经完成但尚未处理的缓冲. 花费的时间取决于cards的密度。cards越多,耗费的时间就越长。</p><p>Scanning Remembered Sets(扫描 RSets)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Scan RS (ms): 0.4 0.2 0.1 0.3 0.0 0.0 0.1 0.2 0.0 0.1 0.0 0.0 Avg: 0.1, Min: 0.0, Max: 0.4, Diff: 0.3]F</span><br></pre></td></tr></table></figure><p><code>Scanning Remembered Sets</code> - 查找指向 Collection Set 的指针(pointers)</p><p>Object Copy(对象拷贝)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Object Copy (ms): 16.7 16.7 16.7 16.9 16.0 18.1 16.5 16.8 16.7 12.3 16.4 15.7 Avg: 16.3, Min: 12.3, Max:  18.1, Diff: 5.8]</span><br></pre></td></tr></table></figure><p><code>Object copy</code> – 每个独立的线程在拷贝和转移对象时所消耗的时间.</p><p>Termination Time(结束时间)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[Termination (ms): 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0</span><br><span class="line">0.0 Avg: 0.0, Min: 0.0, Max: 0.0, Diff: 0.0] [Termination Attempts : 1 1 1 1 1 1 1 1 1 1 1 1 Sum: 12, Avg: 1, Min: 1, Max: 1, Diff: 0]</span><br></pre></td></tr></table></figure><p><code>Termination time</code> - 当worker线程完成了自己那部分对象的复制和扫描,就进入终止协议(termination protocol)。它查找未完成的工作(looks for work to steal), 一旦它完成就会再进入终止协议。 终止尝试记录(Termination attempt counts)所有查找工作的尝试次数(attempts to steal work).</p><p>GC Worker End</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[GC Worker End (ms): 7116.4 7116.3 7116.4 7116.3 7116.4 7116.3 7116.4 7116.4 7116.4 7116.4 7116.3 7116.3</span><br><span class="line">    Avg: 7116.4, Min: 7116.3, Max: 7116.4, Diff:   0.1]</span><br><span class="line">[GC Worker (ms): 20.4 20.3 20.3 20.2 20.3 20.2 20.2 20.2 20.3 20.2 20.1 20.1</span><br><span class="line">     Avg: 20.2, Min: 20.1, Max: 20.4, Diff: 0.3]</span><br></pre></td></tr></table></figure><p><code>GC worker end time</code> – 独立的 GC worker 停止时的时间戳.</p><p><code>GC worker time</code> – 每个独立的 GC worker 线程消耗的时间.</p><p>GC Worker Other</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[GC Worker Other (ms): 2.6 2.6 2.7 2.7 2.7 2.7 2.7 2.8 2.8 2.8 2.8 2.8</span><br><span class="line">    Avg: 2.7, Min: 2.6, Max: 2.8, Diff: 0.2]</span><br></pre></td></tr></table></figure><p><code>GC worker other</code> – 每个GC线程中不能归属到之前列出的worker阶段的其他时间. 这个值应该很低. 过去我们见过很高的值,是由于JVM的其他部分的瓶颈引起的(例如在分层[Tiered]代码缓存[Code Cache]占有率的增加)。</p><p>Clear CT</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Clear CT: 0.6 ms]</span><br></pre></td></tr></table></figure><p>清除 RSet 扫描元数据(scanning meta-data)的 card table 消耗的时间.</p><p>Other</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Other: 6.8 ms]</span><br></pre></td></tr></table></figure><p>其他各种GC暂停的连续阶段花费的时间.</p><p>CSet</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Choose CSet: 0.1 ms]</span><br></pre></td></tr></table></figure><p>敲定要进行垃圾回收的region集合时消耗的时间. 通常很小,在必须选择 old 区时会稍微长一点点.</p><p>Ref Proc</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Ref Proc: 4.4 ms]</span><br></pre></td></tr></table></figure><p>处理 soft, weak, 等引用所花费的时间,不同于前面的GC阶段</p><p>Ref Enq</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Ref Enq: 0.1 ms]</span><br></pre></td></tr></table></figure><p>将 soft, weak, 等引用放置到待处理列表(pending list)花费的时间.</p><p>Free CSet</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[Free CSet: 2.0 ms]</span><br></pre></td></tr></table></figure><p>释放刚被垃圾收集的 heap区所消耗的时间,包括对应的remembered sets。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在此OBE中, 您对Java JVM 中的G1垃圾收集器有了个大致的了解。首先你学到了为何堆和垃圾收集器是所有Java JVM的关键部分。接下来讲述了使用CMS和G1收集器进行垃圾回收的工作方式. 接下来,您了解了G1的命令行参数&#x2F;开关以及和使用它们的最佳实践。最后,您了解了日志对象以及GC日志中的数据。</p><p>在本教程中,你学到了这些知识:</p><ul><li>Java JVM 的组成部分</li><li>对 G1 的概述</li><li>概述 CMS 垃圾收集器</li><li>概述 G1 垃圾收集器</li><li>命令行参数与最佳实践</li><li>G1 的日志信息</li></ul><h3 id="相关资源"><a href="#相关资源" class="headerlink" title="相关资源"></a>相关资源</h3><p>更多相关信息请参考以下网站链接.</p><ul><li><a target="_blank" rel="noopener external nofollow noreferrer" href="http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html">HotSpot 虚拟机参数</a></li><li><a target="_blank" rel="noopener external nofollow noreferrer" href="http://www.oracle.com/technetwork/java/javase/tech/g1-intro-jsp-135488.html">G1(垃圾优先)收集器</a></li><li><a target="_blank" rel="noopener external nofollow noreferrer" href="https://blogs.oracle.com/poonam/entry/understanding_g1_gc_logs">Poonam Bajaj的博客： G1垃圾回收日志</a></li><li><a target="_blank" rel="noopener external nofollow noreferrer" href="http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=609&p_org_id=1001&lang=US&get_params=dc:D67232GC10,p_preview:N">Java SE 7: 开发富客户端应用程序</a></li><li><a target="_blank" rel="noopener external nofollow noreferrer" href="http://www.amazon.cn/gp/product/B00IOB0K1Q">Java性能优化权威指南 – 中文版</a></li><li><a target="_blank" rel="noopener external nofollow noreferrer" href="http://www.oracle.com/oll">Oracle 学习资料库</a></li></ul></article><div class="post-copyright"><div class="copyright-cc-box"><i class="anzhiyufont anzhiyu-icon-copyright"></i></div><div class="post-copyright__author_box"><a class="post-copyright__author_img" href="/" title="头像"><img class="post-copyright__author_img_back" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://q1.qlogo.cn/g?b=qq&amp;nk=2071916845&amp;s=640" title="头像" alt="头像"><img class="post-copyright__author_img_front" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://q1.qlogo.cn/g?b=qq&amp;nk=2071916845&amp;s=640" title="头像" alt="头像"></a><div class="post-copyright__author_name">云少</div><div class="post-copyright__author_desc">站在巨人的肩膀罢了</div></div><div class="post-copyright__post__info"><a class="post-copyright__original" title="该文章为原创文章，注意版权协议" href="https://it985.github.io/posts/5333e17a.html">原创</a><a class="post-copyright-title"><span onclick='rm.copyPageUrl("https://it985.github.io/posts/5333e17a.html")'>一、GC 性能优化 – G1垃圾收集器入门</span></a></div><div class="post-tools" id="post-tools"><div class="post-tools-left"><div class="rewardLeftButton"><div class="post-reward" onclick="anzhiyu.addRewardMask()"><div class="reward-button button--animated" title="赞赏作者"><i class="anzhiyufont anzhiyu-icon-hand-heart-fill"></i>打赏作者</div><div class="reward-main"><div class="reward-all"><span class="reward-title">感谢你赐予我前进的力量</span><ul class="reward-group"><li class="reward-item"><a href="/img/wxpay.webp" target="_blank"><img class="post-qr-code-img" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="/img/wxpay.webp" alt="wechat"></a><div class="post-qr-code-desc">wechat</div></li><li class="reward-item"><a href="/img/alipay.webp" target="_blank"><img class="post-qr-code-img" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="/img/alipay.webp" alt="alipay"></a><div class="post-qr-code-desc">alipay</div></li></ul><a class="reward-main-btn" href="/about/#about-reward" target="_blank"><div class="reward-text">赞赏者名单</div><div class="reward-dec">因为你们的支持让我意识到写文章的价值🙏</div></a></div></div></div><div id="quit-box" onclick="anzhiyu.removeRewardMask()" style="display:none"></div></div><div class="shareRight"><div class="share-link mobile"><div class="share-qrcode"><div class="share-button" title="使用手机访问这篇文章"><i class="anzhiyufont anzhiyu-icon-qrcode"></i></div><div class="share-main"><div class="share-main-all"><div id="qrcode" title="https://it985.github.io/posts/5333e17a.html"></div><div class="reward-dec">使用手机访问这篇文章</div></div></div></div></div><div class="share-link weibo"><a class="share-button" target="_blank" href="https://service.weibo.com/share/share.php?title=一、GC 性能优化 – G1垃圾收集器入门&amp;url=https://it985.github.io/posts/5333e17a.html&amp;pic=https://cn.bing.com/th?id=OHR.FanalMadeira_EN-US8481108715_UHD.jpg" rel="external nofollow noreferrer noopener"><i class="anzhiyufont anzhiyu-icon-weibo"></i></a></div><div class="share-link copyurl"><div class="share-button" id="post-share-url" title="复制链接" onclick="rm.copyPageUrl()"><i class="anzhiyufont anzhiyu-icon-link"></i></div></div></div></div></div><div class="post-copyright__notice"><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://it985.github.io" target="_blank">云少IT</a>！</span></div></div><div class="post-tools-right"><div class="tag_share"><div class="post-meta__box"><div class="post-meta__box__tag-list"><a class="post-meta__box__tags" href="/tags/JVM/"><span class="tags-punctuation"><i class="anzhiyufont anzhiyu-icon-tag"></i></span>JVM<span class="tagsPageCount">8</span></a></div></div><div class="post_share"><div class="social-share" data-image="https://img02.anheyu.com/adminuploads/1/2022/09/05/6315e146a8bbd.webp" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.cbd.int/butterfly-extsrc@1.1.3/sharejs/dist/css/share.min.css" media="print" onload='this.media="all"'><script src="https://cdn.cbd.int/butterfly-extsrc@1.1.3/sharejs/dist/js/social-share.min.js" defer></script></div></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/posts/7c7b9156.html"><img class="prev-cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.CapelCurig_EN-US8402685568_UHD.jpg" onerror='onerror=null,src="/img/404.jpg"' alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">二十三、PHP 连接 Memcached 服务</div></div></a></div><div class="next-post pull-right"><a href="/posts/add0ca35.html"><img class="next-cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://img.xjh.me/random_img.php?type=bg&amp;ctype=nature&amp;return=302&amp;_r_=956f847d-bfd5-0cd9-0efd-045fd14163ea" onerror='onerror=null,src="/img/404.jpg"' alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">专栏汇总：GC 性能优化</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="anzhiyufont anzhiyu-icon-thumbs-up fa-fw" style="font-size:1.5rem;margin-right:4px"></i><span>喜欢这篇文章的人也看了</span></div><div class="relatedPosts-list"><div><a href="/posts/727d80c8.html" title="八、GC 性能优化 – GC 调优(实战篇)"><img class="cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.MarigoldsLosMuertos_EN-US5597948262_UHD.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> 2019-01-31</div><div class="title">八、GC 性能优化 – GC 调优(实战篇)</div></div></a></div><div><a href="/posts/c219fcd0.html" title="七、GC 性能优化 – GC 调优(工具篇)"><img class="cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.KindredSpirits_EN-US5529252474_UHD.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> 2019-01-30</div><div class="title">七、GC 性能优化 – GC 调优(工具篇)</div></div></a></div><div><a href="/posts/1cbf2ab0.html" title="六、GC 性能优化 – GC 调优(基础篇)"><img class="cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.MistyForest_EN-US5261676101_UHD.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> 2019-01-29</div><div class="title">六、GC 性能优化 – GC 调优(基础篇)</div></div></a></div><div><a href="/posts/46b81885.html" title="五、GC 性能优化 – GC 算法(实现篇)"><img class="cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.Dargavs_EN-US4957085337_UHD.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> 2019-01-28</div><div class="title">五、GC 性能优化 – GC 算法(实现篇)</div></div></a></div><div><a href="/posts/a63b36e1.html" title="四、GC 性能优化 – GC 算法(基础篇)"><img class="cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.RedFoxBlackForest_EN-US4823848176_UHD.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> 2019-01-27</div><div class="title">四、GC 性能优化 – GC 算法(基础篇)</div></div></a></div><div><a href="/posts/2711940d0c.html" title="三、GC 性能优化 – Java中的垃圾收集"><img class="cover" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://cn.bing.com/th?id=OHR.Bavljenac_EN-US8692148480_UHD.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="anzhiyufont anzhiyu-icon-calendar-days fa-fw"></i> 2019-01-26</div><div class="title">三、GC 性能优化 – Java中的垃圾收集</div></div></a></div></div></div><hr><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="anzhiyufont anzhiyu-icon-comments"></i><span> 评论</span></div><div class="comment-randomInfo"><a onclick="anzhiyu.addRandomCommentInfo()" href="javascript:void(0)" rel="external nofollow noreferrer">匿名评论</a><a href="/privacy" style="margin-left:4px">隐私政策</a></div><div class="comment-switch"><span class="first-comment">Twikoo</span><span id="switch-btn"></span><span class="second-comment">Artalk</span></div><div class="comment-tips" id="comment-tips"><span>✅ 你无需删除空行，直接评论以获取最佳展示效果</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div><div><div id="artalk-wrap"></div></div></div></div><div class="comment-barrage"></div></div><div class="aside-content" id="aside-content"><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="anzhiyufont anzhiyu-icon-bars"></i><span>文章目录</span><span class="toc-percentage"></span></div><div class="toc-content is-expand"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E4%B8%80%E3%80%81GC-%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96-%E2%80%93-G1%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E5%85%A5%E9%97%A8"><span class="toc-number">1.</span> <span class="toc-text">一、GC 性能优化 – G1垃圾收集器入门</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#G1%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E5%85%A5%E9%97%A8"><span class="toc-number">2.</span> <span class="toc-text">G1垃圾收集器入门</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%AF%B4%E6%98%8E"><span class="toc-number">2.1.</span> <span class="toc-text">说明</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%A6%82%E8%BF%B0"><span class="toc-number">2.2.</span> <span class="toc-text">概述</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Java-%E6%8A%80%E6%9C%AF-%E5%92%8C-JVM"><span class="toc-number">2.3.</span> <span class="toc-text">Java 技术 和 JVM</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#Java-%E6%A6%82%E8%BF%B0"><span class="toc-number">2.3.1.</span> <span class="toc-text">Java 概述</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8E%A2%E7%B4%A2-JVM-%E4%BD%93%E7%B3%BB%E6%9E%B6%E6%9E%84"><span class="toc-number">2.3.2.</span> <span class="toc-text">探索 JVM 体系架构</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%80%A7%E8%83%BD%E5%9F%BA%E7%A1%80"><span class="toc-number">2.3.3.</span> <span class="toc-text">性能基础</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#G1-%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8-Garbage-Collector"><span class="toc-number">2.4.</span> <span class="toc-text">G1 垃圾收集器(Garbage Collector)</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#G1-%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8"><span class="toc-number">2.4.1.</span> <span class="toc-text">G1 垃圾收集器</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#CMS%E7%9A%84GC%E6%A6%82%E8%BF%B0"><span class="toc-number">2.5.</span> <span class="toc-text">CMS的GC概述</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%86%E4%BB%A3GC-Generational-GC-%E4%B8%8E-CMS"><span class="toc-number">2.5.1.</span> <span class="toc-text">分代GC(Generational GC)与 CMS</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#G1%E5%9E%83%E5%9C%BE%E6%94%B6%E9%9B%86%E5%99%A8%E6%A6%82%E8%BF%B0"><span class="toc-number">2.6.</span> <span class="toc-text">G1垃圾收集器概述</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%80%E6%AD%A5%E6%AD%A5%E4%BB%8B%E7%BB%8DG1"><span class="toc-number">2.6.1.</span> <span class="toc-text">一步步介绍G1</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Old-Generation-Collection-with-G1"><span class="toc-number">2.6.2.</span> <span class="toc-text">Old Generation Collection with G1</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5"><span class="toc-number">2.7.</span> <span class="toc-text">命令行参数与最佳实践</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0%E4%B8%8E%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5-1"><span class="toc-number">2.7.1.</span> <span class="toc-text">命令行参数与最佳实践</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%AE%B0%E5%BD%95G1%E7%9A%84GC%E6%97%A5%E5%BF%97"><span class="toc-number">2.8.</span> <span class="toc-text">记录G1的GC日志</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%AE%B0%E5%BD%95G1%E7%9A%84GC%E6%97%A5%E5%BF%97-1"><span class="toc-number">2.8.1.</span> <span class="toc-text">记录G1的GC日志</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%BB%E7%BB%93"><span class="toc-number">2.9.</span> <span class="toc-text">总结</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%9B%B8%E5%85%B3%E8%B5%84%E6%BA%90"><span class="toc-number">2.9.1.</span> <span class="toc-text">相关资源</span></a></li></ol></li></ol></li></ol></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div id="footer_deal"><a class="deal_link" href="mailto:2071916845@qq.com" rel="external nofollow noreferrer" title="email"><i class="anzhiyufont anzhiyu-icon-envelope"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://weibo.com/" title="微博"><i class="anzhiyufont anzhiyu-icon-weibo"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.facebook.com/" title="facebook"><i class="anzhiyufont anzhiyu-icon-facebook1"></i></a><a class="deal_link" href="/atom.xml" title="RSS"><i class="anzhiyufont anzhiyu-icon-rss"></i></a><img class="footer_mini_logo" title="返回顶部" alt="返回顶部" onclick="anzhiyu.scrollToDest(0,500)" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://q1.qlogo.cn/g?b=qq&amp;nk=2071916845&amp;s=640" size="50px"><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/it985" title="Github"><i class="anzhiyufont anzhiyu-icon-github"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://space.bilibili.com/300767383" title="Bilibili"><i class="anzhiyufont anzhiyu-icon-bilibili"></i></a><a class="deal_link" target="_blank" rel="noopener external nofollow noreferrer" href="https://v.douyin.com/" title="抖音"><i class="anzhiyufont anzhiyu-icon-tiktok"></i></a><a class="deal_link" href="/copyright" title="CC"><i class="anzhiyufont anzhiyu-icon-copyright-line"></i></a></div><div id="anzhiyu-footer"><div class="footer-group"><div class="footer-title">服务</div><div class="footer-links"><a class="footer-item" title="51la统计" target="_blank" rel="noopener external nofollow noreferrer" href="https://v6.51.la/">51la统计</a><a class="footer-item" title="十年之约" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.foreverblog.cn/">十年之约</a><a class="footer-item" title="开往" target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/travellings-link/travellings">开往</a></div></div><div class="footer-group"><div class="footer-title">导航</div><div class="footer-links"><a class="footer-item" title="即刻短文" href="/essay/">即刻短文</a><a class="footer-item" title="友链文章" href="/fcircle/">友链文章</a><a class="footer-item" title="留言板" href="/comments/">留言板</a></div></div><div class="footer-group"><div class="footer-title">协议</div><div class="footer-links"><a class="footer-item" title="免责声明" href="/disclaimer/">免责声明</a><a class="footer-item" title="隐私协议" href="/privacy/">隐私协议</a><a class="footer-item" title="Cookies" href="/cookies/">Cookies</a><a class="footer-item" title="版权协议" href="/copyright/">版权协议</a></div></div><div class="footer-group"><div class="footer-title">娱乐</div><div class="footer-links"><a class="footer-item" title="小空调" href="/air-conditioner/">小空调</a><a class="footer-item" title="围住小猫" href="/catch-cat/">围住小猫</a><a class="footer-item" title="免费图床" href="/huluxiapicture/">免费图床</a></div></div><div class="footer-group"><div class="footer-title">推荐分类</div><div class="footer-links"><a class="footer-item" title="Java" href="/categories/Java/">Java</a><a class="footer-item" title="面试" href="/categories/%E9%9D%A2%E8%AF%95/">面试</a></div></div><div class="footer-group"><div class="footer-title-group"><div class="footer-title">友链</div><a class="random-friends-btn" id="footer-random-friends-btn" href="javascript:addFriendLinksInFooter();" rel="external nofollow noreferrer" title="换一批友情链接"><i class="anzhiyufont anzhiyu-icon-arrow-rotate-right"></i></a></div><div class="footer-links" id="friend-links-in-footer"></div></div></div><div id="workboard"><img class="workSituationImg boardsign" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.0.4/img/badge/安知鱼-上班摸鱼中.svg" alt="距离月入25k也就还差一个大佬带我~" title="距离月入25k也就还差一个大佬带我~"><div id="runtimeTextTip"></div></div><div class="wordcount"></div><span>云少已经写了 996.7k 字，</span><span>好像写完一本我国著名的 四大名著 了！！！</span><p id="ghbdages"><a class="github-badge" target="_blank" href="https://hexo.io/" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="博客框架为Hexo_v5.4.0" title="博客框架为Hexo_v5.4.0"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.1.5/img/badge/Frame-Hexo.svg" alt="博客框架为Hexo_v5.4.0"></a><a class="github-badge" target="_blank" href="https://www.upyun.com/?utm_source=lianmeng&amp;utm_medium=referral" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="本站使用又拍云为静态资源提供CDN加速" title="本站使用又拍云为静态资源提供CDN加速"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://img.shields.io/badge/CDN-%E5%8F%88%E6%8B%8D%E4%BA%91-orange%3Fstyle%3Dflat%26logo%3D%E5%8F%88%E6%8B%8D%E4%BA%91" alt="本站使用又拍云为静态资源提供CDN加速"></a><a class="github-badge" target="_blank" href="https://github.com/" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="本站项目由Github托管" title="本站项目由Github托管"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.1.5/img/badge/Source-Github.svg" alt="本站项目由Github托管"></a><a class="github-badge" target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可" title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://npm.elemecdn.com/anzhiyu-blog@2.2.0/img/badge/Copyright-BY-NC-SA.svg" alt="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"></a><a class="github-badge" target="_blank" href="https://icp.gov.moe/?keyword=20221607" rel="external nofollow noreferrer" style="margin-inline:5px" data-title="萌ICP备20221607号" title="萌ICP备20221607号"><img src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://img.shields.io/badge/%E8%90%8CICP%E5%A4%87-20221607-fe1384?style-flat&amp;logo=" alt="萌ICP备20221607号"></a></p></div><div id="footer-bar"><div class="footer-bar-links"><div class="footer-bar-left"><div id="footer-bar-tips"><div class="copyright">&copy;2018 - 2023 By <a class="footer-bar-link" href="/" title="云少" target="_blank">云少</a></div></div><div id="footer-type-tips"></div><div class="js-pjax"><script>function subtitleType(){fetch("https://v1.hitokoto.cn").then(t=>t.json()).then(t=>{var e="出自 "+t.from,p=[];p.unshift(t.hitokoto,e),window.typed=new Typed("#footer-type-tips",{strings:p,startDelay:300,typeSpeed:150,loop:!0,backSpeed:50})})}"function"==typeof Typed?subtitleType():getScript("https://cdn.cbd.int/typed.js@2.0.15/dist/typed.umd.js").then(subtitleType)</script></div></div><div class="footer-bar-right"><a class="footer-bar-link" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top" title="云少">云少</a><a class="footer-bar-link" target="_blank" rel="noopener external nofollow noreferrer" href="https://beian.miit.gov.cn/" title="鄂ICP备2021021095号-2">鄂ICP备2021021095号-2</a><a class="footer-bar-link cc" href="/copyright" title="cc协议"><i class="anzhiyufont anzhiyu-icon-copyright-line"></i><i class="anzhiyufont anzhiyu-icon-creative-commons-by-line"></i><i class="anzhiyufont anzhiyu-icon-creative-commons-nc-line"></i><i class="anzhiyufont anzhiyu-icon-creative-commons-nd-line"></i></a></div></div></div></footer></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="sidebar-site-data site-data is-center"><a href="/archives/" title="archive"><div class="headline">文章</div><div class="length-num">861</div></a><a href="/tags/" title="tag"><div class="headline">标签</div><div class="length-num">35</div></a><a href="/categories/" title="category"><div class="headline">分类</div><div class="length-num">6</div></a></div><span class="sidebar-menu-item-title">功能</span><div class="sidebar-menu-item"><a class="darkmode_switchbutton menu-child" href="javascript:void(0);" rel="external nofollow noreferrer" title="显示模式"><i class="anzhiyufont anzhiyu-icon-circle-half-stroke"></i><span>显示模式</span></a></div><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">网页</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top/" title="博客"><img class="back-menu-item-icon" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="/img/favicon.ico" alt="博客"><span class="back-menu-item-text">博客</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" target="_blank" rel="noopener external nofollow noreferrer" href="https://www.tryrun.top" title="图床"><img class="back-menu-item-icon" src= "" onerror="this.onerror=null,this.src=&quot;/img/404.jpg&quot;" data-lazy-src="https://www.tryrun.top/favicon.ico" alt="图床"><span class="back-menu-item-text">图床</span></a></div></div></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>望四方</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/archives/"><i class="anzhiyufont anzhiyu-icon-box-archive faa-tada" style="font-size:.9em"></i><span> 归名档</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/categories/"><i class="anzhiyufont anzhiyu-icon-shapes faa-tada" style="font-size:.9em"></i><span> 归四类</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/tags/"><i class="anzhiyufont anzhiyu-icon-tags faa-tada" style="font-size:.9em"></i><span> 书中签</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/charts/"><i class="fa-fw fas fa-chart-bar faa-tada"></i><span> 统计</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>友链</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/link/"><i class="anzhiyufont anzhiyu-icon-link faa-tada" style="font-size:.9em"></i><span> 四方好友</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/fcircle/"><i class="anzhiyufont anzhiyu-icon-artstation faa-tada" style="font-size:.9em"></i><span> 朋友圈</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/comments/"><i class="anzhiyufont anzhiyu-icon-envelope faa-tada" style="font-size:.9em"></i><span> 留言板</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>我的</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/bangumis/"><i class="anzhiyufont anzhiyu-icon-bilibili faa-tada" style="font-size:.9em"></i><span> 追番页</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/album/"><i class="anzhiyufont anzhiyu-icon-images faa-tada" style="font-size:.9em"></i><span> 刹那间</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/equipment/"><i class="fas fa-heart faa-tada"></i><span> 我的装备</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/collect/"><i class="fas fa-camcorder faa-tada"></i><span> 观影阁</span></a></li></ul></div><div class="menus_item"><a class="site-page" href="javascript:void(0);" rel="external nofollow noreferrer"><span>关于</span></a><ul class="menus_item_child"><li><a class="site-page child faa-parent animated-hover" href="/about/"><i class="anzhiyufont anzhiyu-icon-paper-plane faa-tada" style="font-size:.9em"></i><span> 关于本人</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/essay/"><i class="anzhiyufont anzhiyu-icon-lightbulb faa-tada" style="font-size:.9em"></i><span> 闲言碎语</span></a></li><li><a class="site-page child faa-parent animated-hover" href="javascript:toRandomPost()" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-shoe-prints1 faa-tada" style="font-size:.9em"></i><span> 随便逛逛</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/disclaimer/"><i class="fas fa-heart faa-tada"></i><span> 免责声明</span></a></li><li><a class="site-page child faa-parent animated-hover" href="/love/"><i class="anzhiyufont anzhiyu-icon-heartbeat faa-tada" style="font-size:.9em"></i><span> 恋爱小屋</span></a></li></ul></div></div><span class="sidebar-menu-item-title">标签</span><div class="card-tags"><div class="item-headline"></div><div class="card-tag-cloud"><a href="/tags/API/" style="font-size:.88rem;color:#758692">API<sup>43</sup></a><a href="/tags/Base64/" style="font-size:.88rem;color:#2584bf">Base64<sup>1</sup></a><a href="/tags/Collectors/" style="font-size:.88rem;color:#bfad3e">Collectors<sup>3</sup></a><a href="/tags/Date/" style="font-size:.88rem;color:#b9b609">Date<sup>3</sup></a><a href="/tags/Executor/" style="font-size:.88rem;color:#14c83c">Executor<sup>9</sup></a><a href="/tags/Guava/" style="font-size:.88rem;color:#0a1878">Guava<sup>1</sup></a><a href="/tags/JVM/" style="font-size:.88rem;color:#625421">JVM<sup>8</sup></a><a href="/tags/Java8/" style="font-size:.88rem;color:#aa71bf">Java8<sup>21</sup></a><a href="/tags/Java9/" style="font-size:.88rem;color:#ad8774">Java9<sup>21</sup></a><a href="/tags/Java%E5%B9%B6%E5%8F%91/" style="font-size:.88rem;color:#19704c">Java并发<sup>20</sup></a><a href="/tags/Lambda/" style="font-size:.88rem;color:#7e5c78">Lambda<sup>4</sup></a><a href="/tags/Lock/" style="font-size:.88rem;color:#700769">Lock<sup>1</sup></a><a href="/tags/Maven/" style="font-size:.88rem;color:#2b8671">Maven<sup>1</sup></a><a href="/tags/Memcached/" style="font-size:.88rem;color:#1b0694">Memcached<sup>23</sup></a><a href="/tags/Mongodb/" style="font-size:.88rem;color:#36202d">Mongodb<sup>49</sup></a><a href="/tags/Queue/" style="font-size:.88rem;color:#643f76">Queue<sup>1</sup></a><a href="/tags/Redis/" style="font-size:.88rem;color:#1e4c38">Redis<sup>27</sup></a><a href="/tags/Stream/" style="font-size:.88rem;color:#a5a097">Stream<sup>4</sup></a><a href="/tags/Thread/" style="font-size:.88rem;color:#05682d">Thread<sup>7</sup></a><a href="/tags/Thread-pool/" style="font-size:.88rem;color:#38ad2a">Thread pool<sup>7</sup></a><a href="/tags/forkJoinPool/" style="font-size:.88rem;color:#827a6b">forkJoinPool<sup>2</sup></a><a href="/tags/stream/" style="font-size:.88rem;color:#4a3ac7">stream<sup>1</sup></a><a href="/tags/%E4%B8%93%E6%A0%8F/" style="font-size:.88rem;color:#b89c14">专栏<sup>35</sup></a><a href="/tags/%E4%BA%8B%E5%8A%A1/" style="font-size:.88rem;color:#922401">事务<sup>1</sup></a><a href="/tags/%E4%BC%98%E5%8C%96/" style="font-size:.88rem;color:#437d09">优化<sup>1</sup></a><a href="/tags/%E5%91%BD%E4%BB%A4/" style="font-size:.88rem;color:#705b06">命令<sup>57</sup></a><a href="/tags/%E5%AE%89%E8%A3%85/" style="font-size:.88rem;color:#06a544">安装<sup>6</sup></a><a href="/tags/%E5%B7%A5%E5%85%B7/" style="font-size:.88rem;color:#c86c4f">工具<sup>2</sup></a><a href="/tags/%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/" style="font-size:.88rem;color:#560b2c">数据类型<sup>8</sup></a><a href="/tags/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/" style="font-size:.88rem;color:#4e0a32">生命周期<sup>1</sup></a><a href="/tags/%E7%AE%80%E4%BB%8B/" style="font-size:.88rem;color:#230f8e">简介<sup>7</sup></a><a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size:.88rem;color:#c0771e">算法<sup>10</sup></a><a href="/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/" style="font-size:.88rem;color:#b40caa">设计模式<sup>38</sup></a><a href="/tags/%E9%85%8D%E7%BD%AE/" style="font-size:.88rem;color:#67389a">配置<sup>2</sup></a><a href="/tags/%E9%9D%A2%E8%AF%95/" style="font-size:.88rem;color:#57425c">面试<sup>11</sup></a></div></div><hr></div></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="anzhiyufont anzhiyu-icon-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="anzhiyufont anzhiyu-icon-circle-half-stroke"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="anzhiyufont anzhiyu-icon-arrows-left-right"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="anzhiyufont anzhiyu-icon-gear"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="anzhiyufont anzhiyu-icon-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="anzhiyufont anzhiyu-icon-comments"></i></a><button type="button" title="切换背景" onclick="toggleWinbox()"><i class="fas fa-display"></i></button><button id="go-up" type="button" title="回到顶部"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i></button></div></div><div id="algolia-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><button class="search-close-button"><i class="anzhiyufont anzhiyu-icon-xmark"></i></button></nav><div class="search-wrap"><div id="algolia-search-input"></div><hr><div id="algolia-search-results"><div id="algolia-hits"></div><div id="algolia-pagination"></div><div id="algolia-info"><div class="algolia-stats"></div><div class="algolia-poweredBy"></div></div></div></div></div><div id="search-mask"></div></div><div id="rightMenu"><div class="rightMenu-group rightMenu-small"><div class="rightMenu-item" id="menu-backward"><i class="anzhiyufont anzhiyu-icon-arrow-left"></i></div><div class="rightMenu-item" id="menu-forward"><i class="anzhiyufont anzhiyu-icon-arrow-right"></i></div><div class="rightMenu-item" id="menu-refresh"><i class="anzhiyufont anzhiyu-icon-arrow-rotate-right" style="font-size:1rem"></i></div><div class="rightMenu-item" id="menu-top"><i class="anzhiyufont anzhiyu-icon-arrow-up"></i></div></div><div class="rightMenu-group rightMenu-line rightMenuPlugin"><div class="rightMenu-item" id="menu-copytext"><i class="anzhiyufont anzhiyu-icon-copy"></i><span>复制选中文本</span></div><div class="rightMenu-item" id="menu-pastetext"><i class="anzhiyufont anzhiyu-icon-paste"></i><span>粘贴文本</span></div><a class="rightMenu-item" id="menu-commenttext"><i class="anzhiyufont anzhiyu-icon-comment-medical"></i><span>引用到评论</span></a><div class="rightMenu-item" id="menu-newwindow"><i class="anzhiyufont anzhiyu-icon-window-restore"></i><span>新窗口打开</span></div><div class="rightMenu-item" id="menu-copylink"><i class="anzhiyufont anzhiyu-icon-link"></i><span>复制链接地址</span></div><div class="rightMenu-item" id="menu-copyimg"><i class="anzhiyufont anzhiyu-icon-images"></i><span>复制此图片</span></div><div class="rightMenu-item" id="menu-downloadimg"><i class="anzhiyufont anzhiyu-icon-download"></i><span>下载此图片</span></div><div class="rightMenu-item" id="menu-newwindowimg"><i class="anzhiyufont anzhiyu-icon-window-restore"></i><span>新窗口打开图片</span></div><div class="rightMenu-item" id="menu-search"><i class="anzhiyufont anzhiyu-icon-magnifying-glass"></i><span>站内搜索</span></div><div class="rightMenu-item" id="menu-searchBaidu"><i class="anzhiyufont anzhiyu-icon-magnifying-glass"></i><span>百度搜索</span></div><div class="rightMenu-item" id="menu-music-toggle"><i class="anzhiyufont anzhiyu-icon-play"></i><span>播放音乐</span></div><div class="rightMenu-item" id="menu-music-back"><i class="anzhiyufont anzhiyu-icon-backward"></i><span>切换到上一首</span></div><div class="rightMenu-item" id="menu-music-forward"><i class="anzhiyufont anzhiyu-icon-forward"></i><span>切换到下一首</span></div><div class="rightMenu-item" id="menu-music-playlist" onclick="window.open(&quot;https://y.qq.com/n/ryqq/playlist/8802438608&quot;, &quot;_blank&quot;);" style="display:none"><i class="anzhiyufont anzhiyu-icon-radio"></i><span>查看所有歌曲</span></div><div class="rightMenu-item" id="menu-music-copyMusicName"><i class="anzhiyufont anzhiyu-icon-copy"></i><span>复制歌名</span></div></div><div class="rightMenu-group rightMenu-line rightMenuOther"><a class="rightMenu-item menu-link" id="menu-randomPost"><i class="anzhiyufont anzhiyu-icon-shuffle"></i><span>随便逛逛</span></a><a class="rightMenu-item menu-link" href="/categories/"><i class="anzhiyufont anzhiyu-icon-cube"></i><span>博客分类</span></a><a class="rightMenu-item menu-link" href="/tags/"><i class="anzhiyufont anzhiyu-icon-tags"></i><span>文章标签</span></a></div><div class="rightMenu-group rightMenu-line rightMenuOther"><a class="rightMenu-item" id="menu-copy" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-copy"></i><span>复制地址</span></a><a class="rightMenu-item" id="menu-commentBarrage" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-message"></i><span class="menu-commentBarrage-text">关闭热评</span></a><a class="rightMenu-item" id="menu-darkmode" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-circle-half-stroke"></i><span class="menu-darkmode-text">深色模式</span></a><a class="rightMenu-item" id="menu-translate" href="javascript:void(0);" rel="external nofollow noreferrer"><i class="anzhiyufont anzhiyu-icon-language"></i><span>轉為繁體</span></a></div></div><div id="rightmenu-mask"></div><div id="he-plugin-simple"></div><script>var WIDGET={CONFIG:{modules:"0124",background:"2",tmpColor:"FFFFFF",tmpSize:"16",cityColor:"FFFFFF",citySize:"16",aqiColor:"E8D87B",aqiSize:"16",weatherIconSize:"24",alertIconSize:"18",padding:"10px 10px 10px 10px",shadow:"0",language:"auto",borderRadius:"20",fixed:"true",vertical:"top",horizontal:"left",left:"20",top:"7.1",key:"df245676fb434a0691ead1c63341cd94"}}</script><link rel="stylesheet" href="https://widget.qweather.net/simple/static/css/he-simple.css?v=1.4.0"><script src="https://widget.qweather.net/simple/static/js/he-simple.js?v=1.4.0"></script><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/js/tw_cn.js"></script><script src="https://cdn.cbd.int/@fancyapps/ui@5.0.20/dist/fancybox/fancybox.umd.js"></script><script src="https://cdn.cbd.int/instant.page@5.2.0/instantpage.js" type="module"></script><script src="https://cdn.cbd.int/vanilla-lazyload@17.8.4/dist/lazyload.iife.min.js"></script><script src="https://cdn.cbd.int/node-snackbar@0.1.16/dist/snackbar.min.js"></script><script>function panguFn(){"object"==typeof pangu?pangu.autoSpacingPage():getScript("https://cdn.cbd.int/pangu@4.0.7/dist/browser/pangu.min.js").then(()=>{pangu.autoSpacingPage()})}function panguInit(){panguFn()}document.addEventListener("DOMContentLoaded",panguInit)</script><script>var meting_api="https://api.injahow.cn/meting/?server=:server&type=:type&id=:id&auth=:auth&r=:r"</script><canvas id="universe"></canvas><script async src="https://npm.elemecdn.com/anzhiyu-theme-static@1.0.0/dark/dark.js"></script><script>var HoldLog=console.log;console.log=function(){};let now1=new Date;queueMicrotask(()=>{function o(){HoldLog.apply(console,arguments)}var c=new Date("09/01/2018 00:00:00"),c=(now1.setTime(now1.getTime()+250),(now1-c)/1e3/60/60/24),c=["欢迎使用安知鱼!","生活明朗, 万物可爱",`
        
       █████╗ ███╗   ██╗███████╗██╗  ██╗██╗██╗   ██╗██╗   ██╗
      ██╔══██╗████╗  ██║╚══███╔╝██║  ██║██║╚██╗ ██╔╝██║   ██║
      ███████║██╔██╗ ██║  ███╔╝ ███████║██║ ╚████╔╝ ██║   ██║
      ██╔══██║██║╚██╗██║ ███╔╝  ██╔══██║██║  ╚██╔╝  ██║   ██║
      ██║  ██║██║ ╚████║███████╗██║  ██║██║   ██║   ╚██████╔╝
      ╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝╚═╝   ╚═╝    ╚═════╝
        
        `,"已上线",Math.floor(c),"天","©2018 By 安知鱼 V1.6.6"],e=["NCC2-036","调用前置摄像头拍照成功，识别为【小笨蛋】.","Photo captured: ","🤪"];setTimeout(o.bind(console,`
%c${c[0]} %c ${c[1]} %c ${c[2]} %c${c[3]}%c ${c[4]}%c ${c[5]}

%c ${c[6]}
`,"color:#425AEF","","color:#425AEF","color:#425AEF","","color:#425AEF","")),setTimeout(o.bind(console,`%c ${e[0]} %c ${e[1]} %c 
${e[2]} %c
${e[3]}
`,"color:white; background-color:#4fd953","","",'background:url("https://npm.elemecdn.com/anzhiyu-blog@1.1.6/img/post/common/tinggge.gif") no-repeat;font-size:450%')),setTimeout(o.bind(console,"%c WELCOME %c 你好，小笨蛋.","color:white; background-color:#4f90d9","")),setTimeout(console.warn.bind(console,"%c ⚡ Powered by 安知鱼 %c 你正在访问 云少 的博客.","color:white; background-color:#f0ad4e","")),setTimeout(o.bind(console,"%c W23-12 %c 你已打开控制台.","color:white; background-color:#4f90d9","")),setTimeout(console.warn.bind(console,"%c S013-782 %c 你现在正处于监控中.","color:white; background-color:#d9534f",""))})</script><script async src="/anzhiyu/random.js"></script><script async>!function(){var n,o,r,a,i,e=new Date("09/01/2018 00:00:00"),l=new Date;setInterval(()=>{var t;if(l=new Date,i=l.getHours(),t=(l-e)/1e3/60/60/24,n=Math.floor(t),t=(l-e)/1e3/60/60-24*n,o=Math.floor(t),1==String(o).length&&(o="0"+o),t=(l-e)/1e3/60-1440*n-60*o,r=Math.floor(t),1==String(r).length&&(r="0"+r),t=(l-e)/1e3-86400*n-3600*o-60*r,a=Math.round(t),1==String(a).length&&(a="0"+a),document.getElementById("footer")){let e="";e=(i<18&&9<=i||((t=document.querySelector("#workboard .workSituationImg")).src="https://npm.elemecdn.com/anzhiyu-blog@2.0.4/img/badge/安知鱼-下班啦.svg",t.title="下班了就该开开心心的玩耍，嘿嘿~",t.alt="下班了就该开开心心的玩耍，嘿嘿~"),`本站居然运行了 ${n} 天<span id='runtime'> ${o} 小时 ${r} 分 ${a} 秒 </span><i class='anzhiyufont anzhiyu-icon-heartbeat' style='color:red'></i>`),document.getElementById("runtimeTextTip")&&(document.getElementById("runtimeTextTip").innerHTML=e)}},1e3)}()</script><script src="https://cdn.cbd.int/algoliasearch@4.18.0/dist/algoliasearch-lite.umd.js"></script><script src="https://cdn.cbd.int/instantsearch.js@4.56.5/dist/instantsearch.production.min.js"></script><script src="/js/search/algolia.js"></script><div class="js-pjax"><script>(()=>{const e=document.querySelectorAll("#article-container .mermaid-wrap");if(0!==e.length){const n=()=>{window.loadMermaid=!0;const a="dark"===document.documentElement.getAttribute("data-theme")?"dark":"default";Array.from(e).forEach((e,t)=>{const n=e.firstElementChild;e="%%{init:{ 'theme':'"+a+"'}}%%\n"+n.textContent;const d=mermaid.render("mermaid-"+t,e);"string"==typeof d?(t=d,n.insertAdjacentHTML("afterend",t)):d.then(({svg:e})=>{n.insertAdjacentHTML("afterend",e)})})};var t=()=>{window.loadMermaid?n():getScript("https://cdn.cbd.int/mermaid@10.2.4/dist/mermaid.min.js").then(n)};anzhiyu.addGlobalFn("themeChange",n,"mermaid"),window.pjax?t():document.addEventListener("DOMContentLoaded",t)}})()</script><script>(()=>{const t=()=>{twikoo.init(Object.assign({el:"#twikoo-wrap",envId:"https://twikoo.tryrun.top/",region:"",onCommentLoaded:()=>{anzhiyu.loadLightbox(document.querySelectorAll("#twikoo .tk-content img:not(.tk-owo-emotion)"))}},null))};var o=()=>{"object"==typeof twikoo?setTimeout(n,0):getScript("https://cdn.cbd.int/twikoo@1.6.18/dist/twikoo.all.min.js").then(n)};const n=()=>{t()};anzhiyu.loadComment(document.getElementById("twikoo-wrap"),o)})()</script><script>(()=>{const t=()=>{window.artalkItem=new Artalk(Object.assign({el:"#artalk-wrap",server:"https://artalk.tryrun.top/",site:"https://blog.tryrun.top/",pageKey:location.pathname,darkMode:"dark"===document.documentElement.getAttribute("data-theme"),countEl:".artalk-count"},null)),"null"!==GLOBAL_CONFIG.lightbox&&window.artalkItem.use(t=>{t.on("list-loaded",()=>{t.getCommentList().forEach(t=>{t=t.getRender().$content;anzhiyu.loadLightbox(t.querySelectorAll("img:not([atk-emoticon])"))})})})};var a=async()=>{"object"==typeof window.artalkItem||(await getCSS("https://cdn.cbd.int/artalk@2.5.5/dist/Artalk.css"),await getScript("https://cdn.cbd.int/artalk@2.5.5/dist/Artalk.js")),t()};anzhiyu.addGlobalFn("themeChange",t=>{var a=document.getElementById("artalk-wrap");a&&a.children.length&&window.artalkItem.setDarkMode("dark"===t)},"artalk"),window.loadOtherComment=a})()</script><input type="hidden" name="page-type" id="page-type" value="post"></div><script>window.addEventListener("load",()=>{const t=e=>e=""!==e&&150<(e=(e=(e=(e=e.replace(/<img.*?src="(.*?)"?[^\>]+>/gi,"[图片]")).replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,"[链接]")).replace(/<pre><code>.*?<\/pre>/gi,"[代码]")).replace(/<[^>]+>/g,"")).length?e.substring(0,150)+"...":e,n=t=>{let n="";if(t.length)for(let e=0;e<t.length;e++)n=(n=(n+="<div class='aside-list-item'>")+`<a href='${t[e].url}' class='thumbnail'><img data-lazy-src='${t[e].avatar}' alt='${t[e].nick}'><div class='name'><span>${t[e].nick} </span></div></a>`)+`<div class='content'>
        <a class='comment' href='${t[e].url}' title='${t[e].content}'>${t[e].content}</a>
        <time datetime="${t[e].date}">${anzhiyu.diffDate(t[e].date,!0)}</time></div>
        </div>`;else n+="没有评论";var e=document.querySelector("#card-newest-comments .aside-list");e.innerHTML=n,window.lazyLoadInstance&&window.lazyLoadInstance.update(),window.pjax&&window.pjax.refresh(e)};var e=()=>{var e;document.querySelector("#card-newest-comments .aside-list")&&((e=saveToLocal.get("twikoo-newest-comments"))?n(JSON.parse(e)):(e=()=>{twikoo.getRecentComments({envId:"https://twikoo.tryrun.top/",region:"",pageSize:6,includeReply:!0}).then(function(e){e=e.map(e=>({content:t(e.comment),avatar:e.avatar,nick:e.nick,url:e.url+"#"+e.id,date:new Date(e.created).toISOString()}));saveToLocal.set("twikoo-newest-comments",JSON.stringify(e),10/1440),n(e)}).catch(function(e){document.querySelector("#card-newest-comments .aside-list").textContent="无法获取评论，请确认相关配置是否正确"})},"object"==typeof twikoo?e():getScript("https://cdn.cbd.int/twikoo@1.6.18/dist/twikoo.all.min.js").then(e)))};e(),document.addEventListener("pjax:complete",e)})</script><script async data-pjax src="https://npm.elemecdn.com/anzhiyu-theme-static@1.0.1/bubble/bubble.js"></script><script>var visitorMail="visitor@anheyu.com"</script><script async data-pjax src="https://cdn.cbd.int/anzhiyu-theme-static@1.0.0/waterfall/waterfall.js"></script><script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/qrcodejs/1.0.0/qrcode.min.js"></script><script src="/js/anzhiyu/right_click_menu.js"></script><link rel="stylesheet" href="https://cdn.cbd.int/anzhiyu-theme-static@1.1.9/icon/ali_iconfont_css.css"><script async src="/js/1.min.js?1"></script><script async src="/js/bg.js?1"></script><script async src="https://cdn1.tianli0.top/npm/sweetalert2@8.19.0/dist/sweetalert2.all.js"></script><script async src="/js/lunar.min.js?1"></script><script async src="/js/day.min.js?1"></script><script async src="/js/winbox.bundle.min.js?1"></script><script id="click-show-text" src="https://cdn.cbd.int/butterfly-extsrc@1.1.3/dist/click-show-text.min.js" data-mobile="true" data-text="富强,民主,文明,和谐,自由,平等,公正,法治,爱国,敬业,诚信,友善" data-fontsize="15px" data-random="true" async></script><link rel="stylesheet" href="https://cdn.cbd.int/anzhiyu-theme-static@1.0.0/aplayer/APlayer.min.css" media="print" onload='this.media="all"'><script src="https://cdn.cbd.int/anzhiyu-blog-static@1.0.1/js/APlayer.min.js"></script><script src="https://cdn.cbd.int/hexo-anzhiyu-music@1.0.1/assets/js/Meting2.min.js"></script><script src="https://cdn.cbd.int/pjax@0.2.8/pjax.min.js"></script><script>let pjaxSelectors=['meta[property="og:image"]','meta[property="og:title"]','meta[property="og:url"]','meta[property="og:type"]','meta[property="og:site_name"]','meta[property="og:description"]',"head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"];var pjax=new Pjax({elements:'a:not([target="_blank"])',selectors:pjaxSelectors,cacheBust:!1,analytics:!0,scrollRestoration:!1});document.addEventListener("pjax:send",function(){if(anzhiyu.removeGlobalFnEvent("pjax"),anzhiyu.removeGlobalFnEvent("themeChange"),document.getElementById("rightside").classList.remove("rightside-show"),window.aplayers)for(let e=0;e<window.aplayers.length;e++)window.aplayers[e].options.fixed||window.aplayers[e].destroy();"object"==typeof typed&&typed.destroy();var e=document.body.classList;e.contains("read-mode")&&e.remove("read-mode")}),document.addEventListener("pjax:complete",function(){window.refreshFn(),document.querySelectorAll("script[data-pjax]").forEach(e=>{const t=document.createElement("script");var a=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach(e=>t.setAttribute(e.name,e.value)),t.appendChild(document.createTextNode(a)),e.parentNode.replaceChild(t,e)}),GLOBAL_CONFIG.islazyload&&window.lazyLoadInstance.update(),"function"==typeof chatBtnFn&&chatBtnFn(),"function"==typeof panguInit&&panguInit(),"function"==typeof gtag&&gtag("config","G-3VMKW5TZBM",{page_path:window.location.pathname}),"object"==typeof _hmt&&_hmt.push(["_trackPageview",window.location.pathname]),"function"==typeof loadMeting&&document.getElementsByClassName("aplayer").length&&loadMeting(),"object"==typeof Prism&&Prism.highlightAll()}),document.addEventListener("pjax:error",e=>{404===e.request.status&&pjax.loadUrl("/404.html")})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><script charset="UTF-8" src="https://cdn.cbd.int/anzhiyu-theme-static@1.1.5/accesskey/accesskey.js"></script></div><div id="popup-window"><div class="popup-window-title">通知</div><div class="popup-window-divider"></div><div class="popup-window-content"><div class="popup-tip">你好呀</div><div class="popup-link"><i class="anzhiyufont anzhiyu-icon-arrow-circle-right"></i></div></div></div></body></html>